编程语言
首页 > 编程语言> > javascript – 如何添加点击以形成循环?

javascript – 如何添加点击以形成循环?

作者:互联网

我将文本数组传递给我的circleCreate函数,该函数为每个文本创建一个楔形.我要做的是向每个楔形添加一个点击事件,因此当用户点击一个楔形时,它会抛出每个楔形文本的警报.

但它不起作用.只有外圈提醒文字.它总是说同样的文字.两个内圈都警告未定义.

http://jsfiddle.net/Yushell/9f7JN/

var layer = new Kinetic.Layer();

function circleCreate(vangle, vradius, vcolor, vtext) {
    startAngle = 0;
    endAngle = 0;
    for (var i = 0; i < vangle.length; i++) {
        // WEDGE
        startAngle = endAngle;
        endAngle = startAngle + vangle[i];
        var wedge = new Kinetic.Wedge({
            x: stage.getWidth() / 2,
            y: stage.getHeight() / 2,
            radius: vradius,
            angleDeg: vangle[i],
            fill: vcolor,
            stroke: 'black',
            strokeWidth: 1,
            rotationDeg: startAngle
        });
        /* CLICK NOT WORKING
        wedge.on('click', function() {
            alert(vtext[i]);
        });*/
        layer.add(wedge);
    }
    stage.add(layer);
}

解决方法:

这是使用异步JavaScript代码(如事件处理程序)遇到的典型问题. circleCreate()函数中的for循环使用一个变量i,它为每个wedge递增.这是很好的你使用我创建楔形的地方:

            angleDeg: vangle[i],

但是在click事件处理程序中使用它会失败:

            alert(vtext[i]);

这是为什么?

当您使用新的Kinetic.Wedge()调用创建楔形时,这将直接在循环内完成.此代码同步运行;它使用i的值,因为它存在于循环的这个特定迭代运行的那一刻.

但是单击事件处理程序在那时不运行.如果你从不点击,它可能根本不运行.当您单击一个楔形时,它的事件处理程序在原始循环完成运行很久之后被调用.

那么,当事件处理程序运行时,i的值是多少?它是最初运行时代码留在其中的任何值.当i等于vangle.length时,这个for循环退出 – 换句话说,我超过了数组的末尾,因此vangle [i]是未定义的.

通过简单地为每个循环迭代调用一个函数,您可以使用闭包轻松解决此问题:

var layer = new Kinetic.Layer();

function circleCreate(vangle, vradius, vcolor, vtext) {
    startAngle = 0;
    endAngle = 0;
    for (var i = 0; i < vangle.length; i++) {
        addWedge( i );
    }
    stage.add(layer);

    function addWedge( i ) {
        startAngle = endAngle;
        endAngle = startAngle + vangle[i];
        var wedge = new Kinetic.Wedge({
            x: stage.getWidth() / 2,
            y: stage.getHeight() / 2,
            radius: vradius,
            angleDeg: vangle[i],
            fill: vcolor,
            stroke: 'black',
            strokeWidth: 1,
            rotationDeg: startAngle
        });
        wedge.on('click', function() {
            alert(vtext[i]);
        });
        layer.add(wedge);
    }
}

现在发生的是调用addWedge()函数为每个循环迭代单独捕获i的值.如您所知,每个函数都可以拥有自己的局部变量/参数,而addWedge()内部的i是该函数的本地函数 – 具体而言,该函数的每个单独调用都是本地的. (注意,因为addWedge()是它自己的函数,所以该函数中的i与外circleCreate()函数中的i不同.如果这是令人困惑的,可以给它一个不同的名称.)

Updated fiddle

一个更好的方法

这就是说,我建议采用不同的方法来构建数据.当我阅读你的代码时,角度和文本数组引起了我的注意:

var anglesParents = [120, 120, 120];
var parentTextArray = ['Parent1', 'Parent2', 'Parent3'];

对于儿童和孙子,有相似但较长的阵列对.

您可以将这些数组中的值与circleCreate()中的vtext [i]和vangle [i]引用一起使用.

一般情况下,除非有特殊原因要使用这样的并行数组,否则如果将它们组合成单个对象数组,代码将变得更加清晰:

[
    { angle: 120, text: 'Parent1' },
    { angle: 120, text: 'Parent2' },
    { angle: 120, text: 'Parent3' }
]

对于嵌套的圆圈,我们可以更进一步,将所有三个环组合成一个大的对象数组,描述整套嵌套环.你有这些数组的地方:

var anglesParents = [120, 120, 120];
var anglesChildren = [120, 60, 60, 60, 60];
var anglesGrandchildren = [
    33.33, 20, 23.33, 43.33, 22.10, 25.26,
    12.63, 28, 32, 33, 27, 36, 14.4, 9.6
];
var grandchildrenTextArray = [
    'GrandCHild1', 'GrandCHild2', 'GrandCHild3', 'GrandCHild4',
    'GrandCHild5', 'GrandCHild6', 'GrandCHild7', 'GrandCHild8',
    'GrandCHild9', 'GrandCHild10', 'GrandCHild11', 'GrandCHild12',
    'GrandCHild13', 'GrandCHild14', 'GrandCHild15', 'GrandCHild16'
];
var childrenTextArray = [
    'Child1', 'Child2', 'Child3', 'Child4', 'Child5'
];
var parentTextArray = ['Parent1', 'Parent2', 'Parent3'];

这将是:

var rings = [
    {
        radius: 200,
        color: 'grey',
        slices: [
            { angle: 33.33, text: 'GrandChild1' },
            { angle: 20, text: 'GrandChild2' },
            { angle: 23.33, text: 'GrandChild3' },
            { angle: 43.33, text: 'GrandChild4' },
            { angle: 22.10, text: 'GrandChild5' },
            { angle: 25.26, text: 'GrandChild6' },
            { angle: 12.63, text: 'GrandChild7' },
            { angle: 28, text: 'GrandChild8' },
            { angle: 32, text: 'GrandChild9' },
            { angle: 33, text: 'GrandChild10' },
            { angle: 27, text: 'GrandChild10' },
            { angle: 36, text: 'GrandChild12' },
            { angle: 14.4, text: 'GrandChild13' },
            { angle: 9.6, text: 'GrandChild14' }
        ]
    },
    {
        radius: 150,
        color: 'darkgrey',
        slices: [
            { angle: 120, text: 'Child1' },
            { angle: 60, text: 'Child2' },
            { angle: 60, text: 'Child3' },
            { angle: 60, text: 'Child4' },
            { angle: 60, text: 'Child5' }
        ]
    },
    {
        radius: 100,
        color: 'lightgrey',
        slices: [
            { angle: 120, text: 'Parent1' },
            { angle: 120, text: 'Parent2' },
            { angle: 120, text: 'Parent3' }
        ]
    }
];

现在这比原来的更长,所有角度:和text:属性名称,但是这些东西压缩得非常好,服务器和浏览器使用的gzip压缩.

更重要的是,它有助于简化和澄清代码并避免错误.您是否碰巧注意到您的角度孩子和孙子的文字阵列长度不一样?

标签:kineticjs,javascript,canvas
来源: https://codeday.me/bug/20190831/1778580.html