当您第一次开始使用offset()设置形状或组的旋转点时,您会感到困惑,因为组的位置也发生了变化。
这是我产生的用于包装正确数学的函数。有谁有更好的解决方案?
更长的故事:我发现将偏移量设置为非直觉时需要重新计算形状的(x,y)。恕我直言,想象旋转的过程时,大多数人会根据早期的数学课程将画布概念化。如果我想象黑板和我的数学老师正在谈论旋转三角形,那么她会指向旋转中心,并且我可以想象三角形围绕着手指旋转。我知道在Konvajs中,偏移量与绘图操作有关,并且出于更深层次的原因,它与形状的x,y pos有关系-对于我来说,考虑在旋转绘图位置时旋转是不直观的!
请注意,在以下代码段的函数中,传入的旋转点的x,y位置相对于舞台的左上方。
/*
Set the offset for rotation to the given location and re-position the shape
*/
function RotatePoint(shape, pos){ // where pos = {x: xpos, y: yPos}
var initialPos = shape.getAbsolutePosition();
var moveBy = {x: pos.x - initialPos.x, y: pos.y - initialPos.y};
// offset is relative to initial x,y of shape, so deduct x,y.
shape.offsetX(moveBy.x);
shape.offsetY(moveBy.y);
// reposition x,y because changing offset moves it.
shape.x(initialPos.x + moveBy.x);
shape.y(initialPos.y + moveBy.y);
}
而且在行动...
/*
Set the offset for rotation to the given location and re-position the shape
*/
function RotatePoint(shape, pos){ // where pos = {x: xpos, y: yPos}
var initialPos = shape.getAbsolutePosition();
var moveBy = {x: pos.x - initialPos.x, y: pos.y - initialPos.y};
// offset is relative to initial x,y of shape, so deduct x,y.
shape.offsetX(moveBy.x);
shape.offsetY(moveBy.y);
// reposition x,y because changing offset moves it.
shape.x(initialPos.x + moveBy.x);
shape.y(initialPos.y + moveBy.y);
}
// from here on was just a part-complete project I grabbed to illustrate the above function
// kpi chart is one or more circles.
var outputKpiChart = function(opts){
// Set up the canvas / stage
var stage = new Konva.Stage({container: opts.ele, width: opts.size.width, height: opts.size.height});
var layer = new Konva.Layer({draggable: false});
stage.add(layer);
var theCfg = getFormat('one');
for (var i = 0; i < theCfg.length; i = i + 1){
var cfg = theCfg[i];
var group = new Konva.Group({});
var w = opts.size.width;
var h = opts.size.height;
var r = opts.size.width/4;
var ctr = {x: opts.size.width/2, y: opts.size.height/2};
var circle = new Konva.Circle({
x: w * cfg.pos.x,
y: h * cfg.pos.y,
radius: w * cfg.r,
stroke: '#D4B22B',
strokeWidth: 4,
fill: '#7D8DF9'
});
group.add(circle);
var text = new Konva.Text({
x: w * cfg.pos.x,
y: h * cfg.pos.y,
text: '42',
fill: 'blue',
fontSize: 140,
fontFamily: 'Roboto'
});
text.offset({x: text.getWidth()/2, y: text.getHeight()/2});
group.add(text);
var text1 = new Konva.Text({
x: w * cfg.pos.x,
y: (h * cfg.pos.y) - (w * cfg.r * .25),
text: 'Meaning of Life',
fill: 'blue',
fontSize: 20,
fontFamily: 'Roboto'
});
text1.x(text1.x() + (text.width() - text1.width())/2); // centre over text 1
text1.offset({x: text.getWidth()/2, y: text.getHeight()/2});
group.add(text1);
layer.add(group)
var pos = group.getClientRect();
// set the group rotate point. Note - x,y is relative to top-left of stage !
RotatePoint(group, {x: pos.x + pos.width/2, y: pos.y + pos.height/2});
var c1 = new Konva.Circle({x: group.offsetX(), y: group.offsetY(), radius: 4, fill: 'red'});
layer.add(c1)
// the tween has to be created after the node has been added to the layer
var tween = new Konva.Tween({
node: group,
duration: 4,
rotation: 360,
easing: Konva.Easings.BackEaseOut
});
tween.play();
}
stage.draw();
}
// this is a dashboard project, this func is intended to return positioning
// metrics for complex kpi displays
var getFormat = function(formatName){
switch (formatName){
case 'one': // display a single circle kpi display
config = [{name: 'c1', r: .25, pos: {x: .5, y: .5}, size: {x: .5, y: .5}}]
break;
}
return config;
}
outputKpiChart({ele: '#container', size: {width: 600, height: 300} })
<script src="https://cdnjs.cloudflare.com/ajax/libs/konva/2.5.1/konva.js"></script>
<p>A function to move the rotaton point of a group.</p>
<div id='container' style="display: inline-block; width: 300px, height: 200px; background-color: silver; overflow: hidden; position: relative;"></div>