我认为你做错了。从文档:
- “Kinetic.Animation 在每个动画帧中修改形状的位置。”
所以我认为你应该停止删除形状,而只是更新形状。那么它应该可能动画部分适合你。
html ---
<!DOCTYPE html>
<html>
<head>
<title>Strath</title>
<meta http-equiv="X-UA-Compatible" content="IE=9" />
<script type="text/javascript" src="kinetic-v4.1.2.min.js"></script>
<script src="fiddle.js"></script>
<style type="text/css">
</style>
</head>
<body>
<div id="PureHTML5"></div>
</body>
</html>
js---
var segsToSkip = 0;
var triangle;
window.onload = function() {
var stage = new Kinetic.Stage({
container: "PureHTML5",
width: 300,
height: 300
});
var layer = new Kinetic.Layer();
/*
* create a triangle shape by defining a
* drawing function which draws a triangle
*/
var box = new Kinetic.Shape({
drawFunc: myDrawFunction,
stroke: "white",
strokeWidth: 8
});
var bbox= new Kinetic.Rect({
x:10,
y:10,
width:10,
height:10,
fill: 'green'
});
triangle = new Kinetic.Shape({
drawFunc: function(context) {
context.beginPath();
context.moveTo(10, 10);
context.lineTo(20, 80);
context.quadraticCurveTo(30, 10, 26, 17);
context.closePath();
context.stroke();
},
fill: '#00D2FF',
stroke: 'black',
strokeWidth: 4
});
layer.add(bbox);
// add the triangle shape to the layer
layer.add(box);
layer.add(triangle);
// add the layer to the stage
stage.add(layer);
var animation = new Kinetic.Animation(function(frame) {
console.log(frame.time);
var newSegsToSkip = Math.round(frame.time / 200);
triangle.setX(newSegsToSkip);
triangle.setDrawFunc(function(context) {
context.beginPath();
context.moveTo(newSegsToSkip, 10);
context.lineTo(newSegsToSkip+20, 80);
context.quadraticCurveTo(30, 10, 26, 17);
context.closePath();
context.stroke();
});
}, layer);
var animation2 = new Kinetic.Animation(function(frame) {
var newSegsToSkip = Math.round(frame.time / 200);
if (newSegsToSkip == segsToSkip) return;
else {
segsToSkip = newSegsToSkip;
box.remove();
box = new Kinetic.Shape({
drawFunc: myDrawFunction,
stroke: "black",
strokeWidth: 8
});
layer.add(box);
}
}, layer);
animation.start();
animation2.start();
};
var myDrawFunction = function(context) {
var x = 50;
var y = 50;
var width = 200;
var height = 200;
var radius = 20;
var dashedLength = 6;
var segsToDraw = 58;
context.beginPath();
context.drawDashedBox(x, y, width, height, radius, dashedLength, segsToSkip, segsToDraw);
context.closePath();
// context.stroke();
//this.fill(context);
this.stroke(context);
}
var CP = window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype;
CP.drawDashedBox = function(x, y, width, height, radius, dashedLength, segsToSkip, segsToDraw) {
// init
var env = getStratEnvForRCBox(x, y, width, height, radius, dashedLength, segsToSkip, segsToDraw);
// 'right'->'upper-right'->'down'->'bottom-right'->'left'->'bottom-left'->'up'->'upper-left'->'right'->...
while (env.segsToDraw > 0) {
console.log('drawing direction: ', env.direction, 'segsToDraw:', env.segsToDraw);
env.putToConsole();
if (env.direction == 'right') {
env = drawDashedLineNew(env, x + width - radius, y + height, dashedLength, this);
env.direction = 'bottom-right';
}
else if (env.direction == 'upper-right') {
env = drawDashedArcNew(env, x + width - radius, y + radius, radius, 0, Math.PI / 2, dashedLength, this);
env.direction = 'left';
}
else if (env.direction == 'down') {
env = drawDashedLineNew(env, x, y + height - radius, dashedLength, this);
env.direction = 'bottom-left';
}
else if (env.direction == 'bottom-right') {
env = drawDashedArcNew(env, x + width - radius, y + height - radius, radius, 3 * Math.PI / 2, 2 * Math.PI, dashedLength, this);
env.direction = 'up';
}
else if (env.direction == 'left') {
env = drawDashedLineNew(env, x + radius, y, dashedLength, this);
env.direction = 'upper-left';
}
else if (env.direction == 'bottom-left') {
env = drawDashedArcNew(env, x + radius, y + height - radius, radius, Math.PI, 3 * Math.PI / 2, dashedLength, this);
env.direction = 'right';
}
else if (env.direction == 'up') {
env = drawDashedLineNew(env, x + width, y + radius, dashedLength, this);
env.direction = 'upper-right';
}
else if (env.direction == 'upper-left') {
env = drawDashedArcNew(env, x + radius, y + radius, radius, Math.PI / 2, Math.PI, dashedLength, this);
env.direction = 'down';
}
}
}
function getStratEnvForRCBox(x, y, width, height, radius, dashLength, segsToSkip, segsToDraw) {
var direction = 'right';
var startX, startY;
if (direction == 'down') {
startX = x; startY = y + radius;
} else if (direction == 'right') {
startX = x + radius; startY = y + height;
} else if (direction == 'up') {
startX = x + width; startY = y + height - radius;
} else if (direction == 'left') {
startX = x + width - radius; startY = y;
}
var env = new Environment(startX, startY, 'gap', 0, direction, segsToSkip, segsToDraw);
return env;
}
function drawDashedLineNew(env, endX, endY, dashedLength, context) {
var dx = (endX - env.x), dy = (endY - env.y);
var angle = Math.atan2(dy, dx);
console.log('drawing line: angle =', angle, ' , ', env.gapOrDash, ' =', env.remainingLengthFromLastDraw);
var fromX = env.x, fromY = env.y;
// deal with remining
// we start loop from a fresh dash
if (env.gapOrDash == 'dash') {
// check if we need to skip
if (env.segsToSkip > 0) {
env.segsToSkip --;
} else {
context.moveTo(env.x, env.y);
context.lineTo(env.x + env.remainingLengthFromLastDraw * Math.cos(angle), env.y + env.remainingLengthFromLastDraw * Math.sin(angle));
// check if we quit
env.segsToDraw --;
if (env.segsToDraw == 0) return env;
}
// a full gap
fromX = env.x + (env.remainingLengthFromLastDraw + dashedLength) * Math.cos(angle);
fromY = env.y + (env.remainingLengthFromLastDraw + dashedLength) * Math.sin(angle);
} else if (env.gapOrDash == 'gap') {
fromX = env.x + env.remainingLengthFromLastDraw * Math.cos(angle);
fromY = env.y + env.remainingLengthFromLastDraw * Math.sin(angle);
}
var length = (endX - fromX) / Math.cos(angle);
if (endX - fromX == 0) length = Math.abs(endY - fromY);
var n = length / dashedLength;
var draw = true;
var x = fromX, y = fromY;
context.moveTo(x, y);
for (var i = 0; i < n; i++) {
x += dashedLength * Math.cos(angle);
y += dashedLength * Math.sin(angle);
if (draw) {
// check if we need to skip
if (env.segsToSkip > 0) {
env.segsToSkip --;
} else {
context.lineTo(x,y);
// check if we quit
env.segsToDraw --;
if (env.segsToDraw == 0) return env;
}
} else context.moveTo(x, y);
draw = !draw;
}
// deal with remaining
if (draw) {
// check if we need to skip
if (env.segsToSkip > 0) {
env.segsToSkip --;
} else
context.lineTo(endX, endY);
}
env.x = endX;
env.y = endY;
draw ? env.gapOrDash = 'dash' : env.gapOrDash = 'gap';
env.remainingLengthFromLastDraw = dashedLength - (endX - x) / Math.cos(angle);
return env;
}
function drawDashedArcNew(env, x, y, radius, startAngle, endAngle, dashedLength, context) {
var points = [];
var n = radius * Math.PI * 2/ dashedLength;
var stepAngle = Math.PI * 2 / n;
// deal with remaining
var angle = Math.asin(env.remainingLengthFromLastDraw / 2 / radius) * 2;
if (env.gapOrDash == 'dash') {
var angle = Math.asin(env.remainingLengthFromLastDraw / 2 / radius) * 2;
points.push({
x : (Math.cos(startAngle) * radius) + x,
y : - (Math.sin(startAngle) * radius) + y,
ex : (Math.cos(startAngle + angle) * radius) + x,
ey : - (Math.sin(startAngle + angle) * radius) + y
});
startAngle += stepAngle + angle;
} else {
startAngle += angle;
}
var draw = true;
while(startAngle + stepAngle <= endAngle) {
if (draw) {
points.push({
x : (Math.cos(startAngle) * radius) + x,
y : - (Math.sin(startAngle) * radius) + y,
ex : (Math.cos(startAngle + stepAngle) * radius) + x,
ey : - (Math.sin(startAngle + stepAngle) * radius) + y
});
}
startAngle += stepAngle;
draw = !draw;
}
// deal with the remaining
var endX = (Math.cos(endAngle) * radius) + x;
var endY = - (Math.sin(endAngle) * radius) + y;
//console.log('drawing arc: end-x:', endX, ',end-y:', endY);
if (draw) {
points.push({
x : (Math.cos(startAngle) * radius) + x,
y : - (Math.sin(startAngle) * radius) + y,
ex : endX,
ey : endY
});
}
env.x = endX;
env.y = endY;
draw ? env.gapOrDash = 'dash' : env.gapOrDash = 'gap';
env.remainingLengthFromLastDraw = dashedLength - radius * Math.sin( (endAngle - startAngle) / 2) * 2;
for(p = 0; p < points.length; p++){
//console.log('draw arc seg: from(', points[p].x, ',', points[p].y, ') to (', points[p].ex, ',', points[p].ey, ')');
// check if we need to skip
if (env.segsToSkip > 0) {
env.segsToSkip --;
} else {
context.moveTo(points[p].x, points[p].y);
context.lineTo(points[p].ex, points[p].ey);
// check if we quit
env.segsToDraw --;
if (env.segsToDraw == 0) return env;
}
}
return env;
}
function Environment(x, y, gapOrDash, remainingLengthFromLastDraw, direction, segsToSkip, segsToDraw) {
this.x = x;
this.y = y;
this.gapOrDash = gapOrDash;
this.remainingLengthFromLastDraw = remainingLengthFromLastDraw;
this.direction = direction;
this.segsToSkip = segsToSkip;
this.segsToDraw = segsToDraw;
}
Environment.prototype.putToConsole = function() {
//console.log('Environment:');
//console.log('x:', this.x, ',y:', this.y, 'direction:', this.direction);
//console.log('toSkip:', this.segsToSkip, 'toDraw:', this.segsToDraw);
}