KineticJS:沿样条曲线添加图像

时间:2014-01-15 18:07:08

标签: kineticjs

我想沿Spline添加图像。因此,用户绘制样条曲线,然后绘制后,我想沿着它的路径运行图像。从根本上说,图像将沿着样条的路径重复 关于如何实现这一目标的任何想法?

1 个答案:

答案 0 :(得分:1)

您可以沿样条线间隔放置标记(或图像)

  • 您可以通过调用mySpline.getPoints()来获取Kinetic.Spline的起点。

  • 您可以通过调用内部mySpline.getTensionPoints来获取样条曲线的曲线定义。

  • 第一条曲线是二次曲线(controlX,controlY,endX,endY)

  • 中间曲线是三次曲线。 (control1X,control1Y,control2X,control2Y,endX,endY);

  • 最后一条曲线是二次曲线(controlX,controlY,endX,endY)

使用此信息和某些数学,您可以在每条曲线上间隔放置标记(或图像)。

enter image description here

这是代码和演示:http://jsfiddle.net/m1erickson/8mb9r/

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Prototype</title>
    <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
    <script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.0.0.min.js"></script>
<style>
body{padding:20px;}
#container{
  border:solid 1px #ccc;
  margin-top: 10px;
  width:400px;
  height:350px;
}
</style>        
<script>
$(function(){

    var stage = new Kinetic.Stage({
        container: 'container',
        width: 400,
        height: 350
    });
    var layer = new Kinetic.Layer();
    stage.add(layer);


    var spline = new Kinetic.Line({
      points: [20,100,340,100,200,200,50,200],
      stroke: 'green',
      strokeWidth: 3,
      lineCap: 'round',
      tension: 1,
    });
    layer.add(spline);
    layer.draw();

//
// the following code places markers along the spline at interval
//

    showSplineMarkers(spline,0.25);

    function showSplineMarkers(spline,interval){
        var points = spline.getPoints();
        var length = points.length;
        var tension = spline.getTension();
        var closed = spline.getClosed();
        var tp, len, n, pt1, pt2, pt3, pt4;
        var intervalT=interval;
        var spots=[];

        pt1={x:points[0],y:points[1]};  // starting point of spline


        // return if not a spline (tension==0)
        // return when insufficient spline points are declared

        if(tension==0 || length<=4){ return; }

        // walk along the spline and place markets at interval

        tp = spline.getTensionPoints();
        len = tp.length;
        n = closed ? 0 : 4;


        // the first curve of the spline is Quadratic

        if (!closed) {
            pt2={x:tp[0],y:tp[1]};
            pt3={x:tp[2],y:tp[3]};
            placeAlongQuad(intervalT,pt1,pt2,pt3);
            pt1=pt3;
        }

        // all intermediate curves of the spline are CubicBezier

        while(n < len - 2) {
            pt2={x:tp[n++],y:tp[n++]};
            pt3={x:tp[n++],y:tp[n++]};
            pt4={x:tp[n++],y:tp[n++]};
            placeAlongCubicBezier(intervalT,pt1,pt2,pt3,pt4);
            pt1=pt4;
        }

        // the last curve of the spline is Quadratic

        if (!closed) {
            pt2={x:tp[len-2],y:tp[len-1]};
            pt3={x:points[length-2],y:points[length-1]};
            placeAlongQuad(intervalT,pt1,pt2,pt3);
        }

    }  //  end showSplineMarkers


    // place markers at interval along the Quad curve

    function placeAlongQuad(intervalT,pt1,pt2,pt3){
        for(var i=0.00;i<=1.00;i+=intervalT){
            var pt=getQuadraticBezierXYatT(pt1,pt2,pt3,i);
            spot(pt.x,pt.y);
        }
    }

    // place markers at interval along CubicBez curve

    function placeAlongCubicBezier(intervalT,pt1,pt2,pt3,pt4){
        for(var i=0.00;i<=1.00;i+=intervalT){
            var pt=getCubicBezierXYatT(pt1,pt2,pt3,pt4,i);
            spot(pt.x,pt.y);
        }
    }

    // draw a marker

    function spot(x,y){
        var n=new Kinetic.Circle({
            x:x,
            y:y,
            radius:4,
            fill:"red"
        });
        layer.add(n);
        layer.draw();
    }

    // get XY at interval on Quad

    function getQuadraticBezierXYatT(startPt,controlPt,endPt,T) {
        var x = Math.pow(1-T,2) * startPt.x + 2 * (1-T) * T * controlPt.x + Math.pow(T,2) * endPt.x; 
        var y = Math.pow(1-T,2) * startPt.y + 2 * (1-T) * T * controlPt.y + Math.pow(T,2) * endPt.y; 
        return( {x:x,y:y} );
    }

    // get XY at interval on CubicBez

    function getCubicBezierXYatT(startPt,controlPt1,controlPt2,endPt,T){
        var x=CubicN(T,startPt.x,controlPt1.x,controlPt2.x,endPt.x);
        var y=CubicN(T,startPt.y,controlPt1.y,controlPt2.y,endPt.y);
        return({x:x,y:y});
    }

    // cubic helper formula at T
    function CubicN(T, a,b,c,d) {
        var t2 = T * T;
        var t3 = t2 * T;
        return a + (-a * 3 + T * (3 * a - a * T)) * T
        + (3 * b + T * (-6 * b + b * 3 * T)) * T
        + (c * 3 - c * 3 * T) * t2
        + d * t3;
    }

}); // end $(function(){});

</script>       
</head>

<body>
    <div id="container"></div>
</body>
</html>