我有一个用Flash和ActionScript编写的应用程序。我想用canvas和KineticJS库替换Flash。我遇到了一个小问题。在ActionScript中是方法“ getRect”(http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/DisplayObject.html#getRect%28%29)和“ getBounds”(http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/DisplayObject.html#getBounds%28%29),它们返回对象的minX,minY,宽度和高度。就我而言,这是一层。使用这两个功能,我可以在图层上获得最左侧和最顶部的坐标。然后我只是设置舞台的新位置,所有项目都位于最左上侧。
所以,我想在javascript中创建类似的东西。要获得该图层上最左侧,最顶部的可见点。我必须检查所有的图层和形状,以获取minX和minY。
我制作了示例代码,可以在这里找到:http://jsfiddle.net/JercSi/v63hC/1/
如果shape为“多边形”,则所有坐标x,y均为0,宽度和高度均为0。我期望x = 100,y = 100,width = 100,height = 100。
如果形状是“文本”,则我得到形状的x,y以及正确的宽度和高度-可以,除非旋转形状。对于“文本”对象,我要获取:x = -8和y = 126。而不是x = 150,y = 150。
这是应该返回minX和minY的脚本。它不返回minX,minY,而是将坐标打印到控制台中(对您的浏览器使用FireBug或类似的插件)。
<script type="text/javascript">
var _le = stage.children.length; // get number of children (stage)
var i, j, _le2;
for (i = 0; i < _le; ++i) {
_le2 = stage.children[i].children.length; // get number of children on each layer
for (j = 0; j < _le2; ++j) {
// check all shapes on the layer
console.log(stage.children[i].children[j].getAbsolutePosition());
console.log(stage.children[i].children[j].getX()+", "+stage.children[i].children[j].getY());
console.log(stage.children[i].children[j].getWidth()+", "+stage.children[i].children[j].getHeight());
}
}
</script>
让我总结一下我的问题,我想获取minX和minY,然后设置舞台的新位置-当前位置:
舞台/图层的新位置:
也许这样的事情已经存在-没有计算minX和minY-但我没有找到。
最佳答案
Kinetic.Polygon不会自动计算最小/最大或宽度/高度。
但是您可以轻松进行这些计算,并使多边形报告这些值。
这是一个红色边框所包含的动力学多边形。
边界框是使用添加到多边形的最小/最大,宽度/高度属性定义的。
首先,当给定myPolygon.getPoints时,此代码返回min,max,width,height。
function getPolyBounds(points){
var minX=100000;
var minY=100000;
var maxX=-100000;
var maxY=-100000;
for(var i=0;i<points.length;i++){
var pt=points[i];
if(pt.x<minX){minX=pt.x;}
if(pt.y<minY){minY=pt.y;}
if(pt.x>maxX){maxX=pt.x;}
if(pt.y>maxY){maxY=pt.y;}
}
return({minX:minX,minY:minY,maxX:maxX,maxY:maxY});
}
您可以向动力学多边形添加方法以返回minX和minY。
poly.bounds=getPolyBounds(poly.getPoints());
poly.minX=function(){return(this.getX()+this.bounds.minX-this.getStrokeWidth());};
poly.minY=function(){return(this.getY()+this.bounds.minY-this.getStrokeWidth());};
您可以向动力学多边形添加属性以获取宽度和高度。
poly.bounds=getPolyBounds(poly.getPoints());
poly.width=poly.bounds.maxX-poly.bounds.minX+poly.getStrokeWidth()*2;
poly.height=poly.bounds.maxY-poly.bounds.minY+poly.getStrokeWidth()*2;
[加法:寻找其他形状的边界]
线:(实际上是一条折线):与多边形相同的解决方案(获取所有点的最小/最大)
所有矩形(矩形,图像,文本,子图形):minX / minY始终为getX / getY。
圈子:minX = getX-getRadius,minY = getY-getRadius
可以通过获取所有blob.getPoints()的最小值/最大值来近似曲线(样条线,blob)。
[加法:找到旋转形状的边界]
要获得旋转形状的新边界,请计算原始点的旋转位置,并使用通常的边界方法(上述)。
这段代码将获取已绕其枢轴点旋转了指定的radianAngle的任何点的newXY:
// calculate the distance from the pivot point to the original point
var dx = originalPoint.x - pivotpoint.x;
var dy = originalPoint.y - pivotpoint.y;
var radius = Math.sqrt(dx*dx+dy*dy);
// calculate the unrotated radian angle
var originalAngle=Math.atan2(dy,dx);
// the new angle is the sum of the original angle and rotation angle
var radianAngle+=originalAngle;
// calculate where the original point has been rotated to
var newX = originalPoint.x + radius * Math.cos(radianAngle);
var newY = originalPoint.y + radius * Math.sin(radianAngle);
[加法:找到更精确的曲线边界]
通过沿曲线绘制许多点并找到其最小/最大值,可以为曲线提供更精确的边界框。
此代码将获取构成曲线的XY点。在这些公式中,T是沿曲线的间隔,其中T = 0.00是曲线的起点,T = 1.00是曲线的终点。
// quadratic bezier: T is 0-1
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} );
}
// cubic bezier T is 0-1
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 distance
function CubicN(pct, a,b,c,d) {
var t2 = pct * pct;
var t3 = t2 * pct;
return a + (-a * 3 + pct * (3 * a - a * pct)) * pct
+ (3 * b + pct * (-6 * b + b * 3 * pct)) * pct
+ (c * 3 - c * 3 * pct) * t2
+ d * t3;
}
这是代码和多边形边界的小提琴:http://jsfiddle.net/m1erickson/SYp5j/
<!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-v4.7.0.min.js"></script>
<style>
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:400px;
height:400px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 400,
height: 400
});
var layer = new Kinetic.Layer();
stage.add(layer);
function getPolyBounds(points){
var minX=100000;
var minY=100000;
var maxX=-100000;
var maxY=-100000;
for(var i=0;i<points.length;i++){
var pt=points[i];
if(pt.x<minX){minX=pt.x;}
if(pt.y<minY){minY=pt.y;}
if(pt.x>maxX){maxX=pt.x;}
if(pt.y>maxY){maxY=pt.y;}
}
return({minX:minX,minY:minY,maxX:maxX,maxY:maxY});
}
function newPoly(polypoints){
var poly = new Kinetic.Polygon({
points:polypoints,
x: 25,
y: 25,
fill: 'skyblue',
stroke: 'lightgray',
strokeWidth: 3
});
poly.bounds=getPolyBounds(poly.getPoints());
poly.minX=function(){return(this.getX()+this.bounds.minX-this.getStrokeWidth());};
poly.minY=function(){return(this.getY()+this.bounds.minY-this.getStrokeWidth());};
poly.width=poly.bounds.maxX-poly.bounds.minX+poly.getStrokeWidth()*2;
poly.height=poly.bounds.maxY-poly.bounds.minY+poly.getStrokeWidth()*2;
layer.add(poly);
layer.draw();
return(poly);
}
// test
var polypoints=[];
polypoints.push({x:20,y:50});
polypoints.push({x:120,y:75});
polypoints.push({x:220,y:50});
polypoints.push({x:120,y:200});
polypoints.push({x:20,y:50});
//
var myPoly=newPoly(polypoints);
//
var boundary=new Kinetic.Rect({
x:myPoly.minX(),
y:myPoly.minY(),
width:myPoly.width,
height:myPoly.height,
stroke:"red",
strokeWidth:0.50
});
layer.add(boundary);
layer.draw();
}); // end $(function(){});
</script>
</head>
<body>
<button id="rotateBtn">rotate</button>
<div id="container"></div>
</body>
</html>