html5画布补间/投影

时间:2017-05-23 18:16:51

标签: javascript jquery html5 canvas tween

我正在研究一个小脚本,它应该(最终)在两个路径之间创建一个动画补间动画。它还有很长的路要走,而且我确信有些东西可以做得更好,但这就是我所处的位置以及我遇到的问题:

我想将顶点从矩形的中心(形状一)向外投影到blob的路径上(形状二)。见下图。

发生了什么: Bad

我想要发生什么: Good

我的最终目标是将其作为一个通用脚本,您可以在其中插入形状一和形状二的点,并使它们相互变形。这只是为了我自己的利益,所以我不想在已经完成的情况下使用插件。谢谢!

HTML:

<canvas id="canvas" width="100%" height="100%">
    Canvas is not supported.
</canvas>

JS:

$(function() {
    var canvas = document.getElementById('canvas'),
        ctx = canvas.getContext('2d'),
        baseX = 500,
        baseY = 350;

    ctx.canvas.width  = window.innerWidth;
    ctx.canvas.height = window.innerHeight;

    var Shape = function(baseX, baseY, points) {
        this.baseX = baseX;
        this.baseY = baseY;
        this.points = points;

        this.drawPoints = function(stroke) {
        var points = this.points;
            var rad = 5;

            for (i=0; i<points.length; i++) {
                ctx.beginPath();
                ctx.fillStyle = 'gray';
                var splitPoints = points[i].split(',');

                switch(splitPoints[0]) {
                    case 'm':
                        ctx.arc(splitPoints[1], splitPoints[2], rad, 2 * Math.PI, false);
                        if (stroke === true) {
                            ctx.fill();
                        }
                    break;
                    case 'l':
                        ctx.arc(splitPoints[1], splitPoints[2], rad, 2 * Math.PI, false);
                        if (stroke === true) {
                            ctx.fill();
                        }
                    break;
                    case 'b':
                        ctx.arc(splitPoints[5], splitPoints[6], rad, 2 * Math.PI, false);
                        if (stroke === true) {
                            ctx.fill();
                        }
                    break;
                }
            }
            ctx.closePath();
        }

        this.drawPath = function(stroke) {
            var points = this.points;

            ctx.beginPath();
            for (i=0; i<points.length; i++) {
                var splitPoints = points[i].split(',');

                switch(splitPoints[0]) {
                    case 'm':
                        ctx.moveTo(splitPoints[1], splitPoints[2]);
                    break;
                    case 'l':
                        ctx.lineTo(splitPoints[1], splitPoints[2]); 
                    break;
                    case 'b':
                        ctx.bezierCurveTo(splitPoints[1], splitPoints[2], splitPoints[3], splitPoints[4], splitPoints[5], splitPoints[6]);
                    break;
                }
            }
            ctx.closePath();

            if (stroke === true) {
                ctx.stroke();
            }
        }
    }

    var rectanglePoints = [];
    //type, ptx1, pty1, ptx2, pty2...
    rectanglePoints.push(`m, ${baseX + 200}, ${baseY - 100}`);
    rectanglePoints.push(`l, ${baseX + 200}, ${baseY + 100}`);
    rectanglePoints.push(`l, ${baseX - 200}, ${baseY + 100}`);
    rectanglePoints.push(`l, ${baseX - 200}, ${baseY - 100}`);
    var rectangle = new Shape(baseX, baseY, rectanglePoints);
    rectangle.drawPath(true);
    rectangle.drawPoints(true);

    var blobPoints = [];
    //type, ptx1, pty1, ptx2, pty2...
    blobPoints.push(`m, ${baseX + 100}, ${baseY - 300}`);
    blobPoints.push(`b, ${baseX + 300}, ${baseY - 375}, ${baseX + 250}, ${baseY - 215}, ${baseX + 250}, ${baseY - 200}`);
    blobPoints.push(`b, ${baseX + 150}, ${baseY + 150}, ${baseX + 200}, ${baseY + 150}, ${baseX + 250}, ${baseY + 200}`);
    blobPoints.push(`b, ${baseX + 350}, ${baseY + 300}, ${baseX + 300}, ${baseY + 400}, ${baseX + 50}, ${baseY + 300}`);
    blobPoints.push(`b, ${baseX}, ${baseY + 250}, ${baseX}, ${baseY + 250}, ${baseX - 100}, ${baseY + 200}`);
    blobPoints.push(`b, ${baseX - 350}, ${baseY + 175}, ${baseX - 350}, ${baseY + 175}, ${baseX - 400}, ${baseY}`);
    blobPoints.push(`b, ${baseX - 400}, ${baseY - 300}, ${baseX - 200}, ${baseY - 100}, ${baseX}, ${baseY - 250}`);

    var blob = new Shape(baseX, baseY, blobPoints);
    blob.drawPath(true);
    blob.drawPoints(true);

    var findCentroid = function(points) {
        var xSum = 0;
        var ySum = 0;
        var xPoints = 0;
        var yPoints = 0;
        var centroid = [];

        for (i=0; i<points.length; i++) {
            var splitPoints = points[i].split(',');

            switch(splitPoints[0]) {
                case 'm':
                    xSum += splitPoints[1]/1;
                    ySum += splitPoints[2]/1;
                    xPoints += 1;
                    yPoints += 1;
                break;
                case 'l':
                    xSum += splitPoints[1]/1;
                    ySum += splitPoints[2]/1;
                    xPoints += 1;
                    yPoints += 1;
                break;
                case 'b':
                    xSum += splitPoints[1]/1;
                    ySum += splitPoints[2]/1;
                    xPoints += 1;
                    yPoints += 1;
                break;
            }
        }

        centroid.push(xSum/xPoints);
        centroid.push(ySum/yPoints);
        return centroid;
    }

    var projectPoints = function(shapeOne, shapeTwo) {
        var pointsOne = shapeOne.points;
        var pointsTwo = shapeTwo.points;
        var centroid = findCentroid(rectanglePoints);
        for (var i=0; i<pointsOne.length; i++) {

            //ispointinstroke would be good but it doesn't have wide browser support. Use inpointinpath
            var splitPoints = pointsOne[i].split(',');

            switch(splitPoints[0]) {
                case 'm':
                    x = splitPoints[1]/1;
                    y = splitPoints[2]/1;
                break;
                case 'l':
                    x = splitPoints[1]/1;
                    y = splitPoints[2]/1; 
                break;
                case 'b':
                    x = splitPoints[5]/1;
                    y = splitPoints[6]/1;
                break;
            }

            //get vector between the centroid and the current x,y value
            var vectorX = x - centroid[0]/1;
            var vectorY = y - centroid[1]/1;
            //increment resolution
            var incRes = 100;
            termX = vectorX/incRes;
            termY = vectorY/incRes;

            shapeTwo.drawPath();

            while (ctx.isPointInPath(centroid[0]/1 + termX, centroid[0]/1 + termY)) {
                termX += vectorX/incRes;
                termY += vectorY/incRes;
                console.log(termX);
                console.log(termY);
            }
            ctx.beginPath();
            ctx.moveTo(centroid[0],centroid[1]);
            ctx.lineTo(centroid[0] + termX, centroid[1] + termY);
            ctx.stroke();
            ctx.closePath();

        }
    }

    projectPoints(rectangle, blob);

    var centroid = findCentroid(rectanglePoints);
    ctx.beginPath();
    ctx.arc(centroid[0], centroid[1], 10, 2 * Math.PI, false);
    ctx.fill();
    ctx.closePath();
    });

的jsfiddle: https://jsfiddle.net/6g076jw0/1/

0 个答案:

没有答案