问题描述
在JSXGraph中,我绘制了作用有4个力(箭头)的板(多边形)。我打算将代码用于可变数量的力量(这就是为什么它只适用于4种力量的原因更为普遍)。
可以显示和隐藏强制组件。拖动力箭头(不穿过枢轴点)时,“拖动”事件将触发动画:
第一:显示力量及其手臂,等待2秒 第二:沿力的方向旋转多边形(顺时针或逆时针)。
问题1:动画缓慢且粗糙。我尝试使用“ suspendUpdate”和“ unsuspendUpdate”,但情况变得更糟。可能是我没有在正确的地方使用它。
问题2 :(可能是相关的)我找不到为动画克隆多边形的好方法。还是最好存储其坐标?但是,如果是这样,在旋转/动画后,如何将多边形(加力箭头)重置为其原始位置?
我的完整代码在这里:https://jsfiddle.net/bujowi/j1etgLsp/3/
您可以从244行开始找到为动画调用的函数:
function animateRotation(x1,y1,x2,y2,sign)
欢迎提出任何改进意见和建议。
解决方法
在jsfiddle中,由于拖动事件被多次触发,所以动画看起来很粗糙。因此,动画并行运行多次。在下面的代码中,这由标志is_animated
阻止。如果true
无法启动新动画。
一个较小的,更类似于JSXGraph的问题是,在setInterval
中动画的每一步中,变换都被添加到JSXGraph元素中。这可能会产生奇怪的效果。将转换一次绑定到一个元素更干净,但使转换动态化,例如取决于角度变量:
var angle = 0.03;
let tRot = b1.create('transform',[function() { return sign * angle; },pivot],{ type: 'rotate' });
此外,这将使在动画结束时将多边形旋转回零角度成为可能。因此,在setInterval
中,只有角度变量会增加,并且木板会更新:
let idInterval = setInterval(function() {
angle += 0.03;
b1.update();
// ...
},refreshTime);
这是完整的新动画代码(最后不回头):
function animateRotation(x1,y1,x2,y2,sign) {
if (this.is_animated) {
return;
}
this.is_animated = true;
// Force arrow and arm (distance from pivot)
let Rot1 = b1.create('point',[x1,y1],{ visible: false })
let Rot2 = b1.create('point',[x2,y2],{ visible: false })
let rotArrow = b1.create('arrow',[Rot1,Rot2],{ strokeColor: '#000',strokeWidth: 3,visible: true })
// Polygon
let PolyCopy = []
for (i = 0; i < poly_coord.length; i++) {
PolyCopy.push(b1.create('point',[poly_coord[i][0],poly_coord[i][1]],at))
}
let polyCopy = b1.create('polygon',PolyCopy,{ strokeColor: myBlue,fillColor: myBlue })
// Hide all other force arrows
showAllElements(false)
// Show line of action and distance from pivot for 1s
let lineOfAction = b1.create('line',[[x1,y2]],strokeWidth: 2,dash: 1 })
let perpLine = b1.create('perpendicular',[lineOfAction,Pivot],{ withLabel: false,visible: false })
let isecP = b1.create('intersection',[perpLine,lineOfAction,0],visible: false })
let dist = b1.create('segment',[Pivot,isecP],strokeWidth: 4 })
var that = this; // make "this" available in the interval function
// This is the animation: rotating the polygon for how many 'frames',refreshTime in ms
setTimeout(function() {
b1.removeObject(lineOfAction)
b1.removeObject(perpLine)
b1.removeObject(isecP)
b1.removeObject(dist)
var angle = 0.03;
let tRot = b1.create('transform',{ type: 'rotate' });
tRot.bindTo(PolyCopy);
tRot.bindTo([Rot1,Rot2]);
let frames = 0;
const refreshTime = 50;
let idInterval = setInterval(function() {
angle += 0.03;
b1.update();
if (frames++ > 20) {
that.is_animated = false;
b1.removeObject(polyCopy);
b1.removeObject(rotArrow);
showAllElements(true);
clearInterval(idInterval);
}
},refreshTime)
},1000); // time for showing the line of action and distance
}
在https://jsfiddle.net/fbdzx0ht/3/上实时观看
最良好的祝愿, 阿尔弗雷德