Javascript 规范化SVG以便于存储
我有一个SVG文件要存储在数据库中。将所有对象存储为多边形并存储坐标将非常有用。但是,我使用的文件是从Ilustrator导出的。它确实包含多边形,但也包含变换的矩形和其他形式。元素不必以绝对精度渲染,因此舍入误差不是问题 如何转换转换后的矩形 这没关系:Javascript 规范化SVG以便于存储,javascript,html,canvas,svg,adobe-illustrator,Javascript,Html,Canvas,Svg,Adobe Illustrator,我有一个SVG文件要存储在数据库中。将所有对象存储为多边形并存储坐标将非常有用。但是,我使用的文件是从Ilustrator导出的。它确实包含多边形,但也包含变换的矩形和其他形式。元素不必以绝对精度渲染,因此舍入误差不是问题 如何转换转换后的矩形 这没关系: <polygon points="2694.423,2972.209 2685.76,2982.961 2702.282,2996.274 2710.938,2985.526 "/ canvas与svg之间是否存在性能问题?。我有
<polygon points="2694.423,2972.209 2685.76,2982.961 2702.282,2996.274
2710.938,2985.526 "/
canvas与svg之间是否存在性能问题?。我有大约3000个可单击的对象要渲染。应用变换normaliser步骤可以通过使用来实现
至于第二步,您可能需要为此添加自己的代码。在许多情况下,在转换后将某些svg元素(直线、矩形、圆、椭圆、多边形、多段线和路径)返回到其屏幕x、y值是有意义的。这是通过使用getCTM和matrixTransform 注意:对于带有笔划(*在IE中不可用)的元素,使用vector effect=“非缩放笔划”。 以下是返回各种转换svg元素的屏幕点的代码:
//----build a generic document SVG root to hold svg point---
function screenLine(line,svg)
{
var sCTM = line.getCTM()
var x1=parseFloat(line.getAttribute("x1"))
var y1=parseFloat(line.getAttribute("y1"))
var x2=parseFloat(line.getAttribute("x2"))
var y2=parseFloat(line.getAttribute("y2"))
var mySVGPoint1 = svg.createSVGPoint();
mySVGPoint1.x = x1
mySVGPoint1.y = y1
mySVGPointTrans1 = mySVGPoint1.matrixTransform(sCTM)
line.setAttribute("x1",mySVGPointTrans1.x)
line.setAttribute("y1",mySVGPointTrans1.y)
var mySVGPoint2 = svg.createSVGPoint();
mySVGPoint2.x = x2
mySVGPoint2.y = y2
mySVGPointTrans2= mySVGPoint2.matrixTransform(sCTM)
line.setAttribute("x2",mySVGPointTrans2.x)
line.setAttribute("y2",mySVGPointTrans2.y)
//---force removal of transform--
line.setAttribute("transform","")
line.removeAttribute("transform")
}
function screenCircle(circle,svg)
{
var sCTM = circle.getCTM()
var scaleX = sCTM.a;
var cx=parseFloat(circle.getAttribute("cx"))
var cy=parseFloat(circle.getAttribute("cy"))
var r=parseFloat(circle.getAttribute("r"))
var mySVGPointC = svg.createSVGPoint();
mySVGPointC.x = cx
mySVGPointC.y = cy
mySVGPointTransC = mySVGPointC.matrixTransform(sCTM)
circle.setAttribute("cx",mySVGPointTransC.x)
circle.setAttribute("cy",mySVGPointTransC.y)
circle.setAttribute("r",r*scaleX)
//---force removal of transform--
circle.setAttribute("transform","")
circle.removeAttribute("transform")
}
function screenEllipse(ellipse,svg)
{
var sCTM = ellipse.getCTM()
var scaleX = sCTM.a;
var scaleY = sCTM.d;
var cx=parseFloat(ellipse.getAttribute("cx"))
var cy=parseFloat(ellipse.getAttribute("cy"))
var rx=parseFloat(ellipse.getAttribute("rx"))
var ry=parseFloat(ellipse.getAttribute("ry"))
var mySVGPointC = svg.createSVGPoint();
mySVGPointC.x = cx
mySVGPointC.y = cy
mySVGPointTransC = mySVGPointC.matrixTransform(sCTM)
ellipse.setAttribute("cx",mySVGPointTransC.x)
ellipse.setAttribute("cy",mySVGPointTransC.y)
ellipse.setAttribute("rx",rx*scaleX)
ellipse.setAttribute("ry",ry*scaleY)
//---force removal of transform--
ellipse.setAttribute("transform","")
ellipse.removeAttribute("transform")
}
function screenRect(rect,svg)
{
var sCTM = rect.getCTM()
var scaleX = sCTM.a;
var scaleY = sCTM.d;
var x=parseFloat(rect.getAttribute("x"))
var y=parseFloat(rect.getAttribute("y"))
var width=parseFloat(rect.getAttribute("width"))
var height=parseFloat(rect.getAttribute("height"))
var mySVGPoint = svg.createSVGPoint();
mySVGPoint.x = x
mySVGPoint.y = y
mySVGPointTrans = mySVGPoint.matrixTransform(sCTM)
rect.setAttribute("x",mySVGPointTrans.x)
rect.setAttribute("y",mySVGPointTrans.y)
rect.setAttribute("width",width*scaleX)
rect.setAttribute("height",height*scaleY)
//---force removal of transform--
rect.setAttribute("transform","")
rect.removeAttribute("transform")
}
function screenPolyline(myPoly,svg)
{
var sCTM = myPoly.getCTM()
var pointsList = myPoly.points;
var n = pointsList.numberOfItems;
for(var m=0;m<n;m++)
{
var mySVGPoint = mySVG.createSVGPoint();
mySVGPoint.x = pointsList.getItem(m).x
mySVGPoint.y = pointsList.getItem(m).y
mySVGPointTrans = mySVGPoint.matrixTransform(sCTM)
pointsList.getItem(m).x=mySVGPointTrans.x
pointsList.getItem(m).y=mySVGPointTrans.y
}
//---force removal of transform--
myPoly.setAttribute("transform","")
myPoly.removeAttribute("transform")
}
function screenPath(path,svg)
{
var sCTM = path.getCTM()
var scaleX = sCTM.a;
var scaleY = sCTM.d;
var segList=path.pathSegList
var segs=segList.numberOfItems
//---change segObj values
for(var k=0;k<segs;k++)
{
var segObj=segList.getItem(k)
if(segObj.x && segObj.y )
{
var mySVGPoint = svg.createSVGPoint();
mySVGPoint.x = segObj.x
mySVGPoint.y = segObj.y
mySVGPointTrans = mySVGPoint.matrixTransform(sCTM)
segObj.x=mySVGPointTrans.x
segObj.y=mySVGPointTrans.y
}
if(segObj.x1 && segObj.y1)
{
var mySVGPoint1 = svg.createSVGPoint();
mySVGPoint1.x = segObj.x1
mySVGPoint1.y = segObj.y1
mySVGPointTrans1 = mySVGPoint1.matrixTransform(sCTM)
segObj.x1=mySVGPointTrans1.x
segObj.y1=mySVGPointTrans1.y
}
if(segObj.x2 && segObj.y2)
{
var mySVGPoint2 = svg.createSVGPoint();
mySVGPoint2.x = segObj.x2
mySVGPoint2.y = segObj.y2
mySVGPointTrans2 = mySVGPoint2.matrixTransform(sCTM)
segObj.x2=mySVGPointTrans2.x
segObj.y2=mySVGPointTrans2.y
}
if(segObj.r1)segObj.r1=segObj.r1*scaleX
if(segObj.r2)segObj.r2=segObj.r2*scaleX
}
//---force removal of transform--
path.setAttribute("transform","")
path.removeAttribute("transform")
}
//---changes all transformed points to screen points---
function screenPolygon(myPoly,mySVG)
{
var sCTM = myPoly.getCTM()
var pointsList = myPoly.points;
var n = pointsList.numberOfItems;
for(var m=0;m<n;m++)
{
var mySVGPoint = mySVG.createSVGPoint();
mySVGPoint.x = pointsList.getItem(m).x
mySVGPoint.y = pointsList.getItem(m).y
mySVGPointTrans = mySVGPoint.matrixTransform(sCTM)
pointsList.getItem(m).x=mySVGPointTrans.x
pointsList.getItem(m).y=mySVGPointTrans.y
}
//---force removal of transform--
myPoly.setAttribute("transform","")
myPoly.removeAttribute("transform")
}
/----构建一个通用文档SVG根以保存SVG点---
功能屏幕行(行,svg)
{
var sCTM=line.getCTM()
var x1=parseFloat(line.getAttribute(“x1”))
var y1=parseFloat(line.getAttribute(“y1”))
var x2=parseFloat(line.getAttribute(“x2”))
var y2=parseFloat(line.getAttribute(“y2”))
var mySVGPoint1=svg.createSVGPoint();
mySVGPoint1.x=x1
mySVGPoint1.y=y1
mySVGPointTrans1=mySVGPoint1.matrixTransform(sCTM)
line.setAttribute(“x1”,mySVGPointTrans1.x)
line.setAttribute(“y1”,mySVGPointTrans1.y)
var mySVGPoint2=svg.createSVGPoint();
mySVGPoint2.x=x2
mySVGPoint2.y=y2
mySVGPointTrans2=mySVGPoint2.matrixTransform(sCTM)
line.setAttribute(“x2”,mySVGPointTrans2.x)
line.setAttribute(“y2”,mySVGPointTrans2.y)
//---变换的强制消除--
line.setAttribute(“转换”,“转换”)
行。删除属性(“转换”)
}
功能屏幕圆圈(圆圈、svg)
{
var sCTM=circle.getCTM()
var scaleX=sCTM.a;
var cx=parseFloat(circle.getAttribute(“cx”))
var cy=parseFloat(circle.getAttribute(“cy”))
var r=parseFloat(circle.getAttribute(“r”))
var mySVGPointC=svg.createSVGPoint();
mySVGPointC.x=cx
mysvgpoint c.y=cy
mySVGPointTransC=mySVGPointC.matrixTransform(sCTM)
circle.setAttribute(“cx”,mySVGPointTransC.x)
circle.setAttribute(“cy”,mySVGPointTransC.y)
circle.setAttribute(“r”,r*scaleX)
//---变换的强制消除--
circle.setAttribute(“transform”、“”)
圈。删除属性(“转换”)
}
函数屏幕椭圆(椭圆,svg)
{
var sCTM=eliple.getCTM()
var scaleX=sCTM.a;
var scaleY=sCTM.d;
var cx=parseFloat(ellipse.getAttribute(“cx”))
var cy=parseFloat(ellipse.getAttribute(“cy”))
var rx=parseFloat(ellipse.getAttribute(“rx”))
var ry=parseFloat(ellipse.getAttribute(“ry”))
var mySVGPointC=svg.createSVGPoint();
mySVGPointC.x=cx
mysvgpoint c.y=cy
mySVGPointTransC=mySVGPointC.matrixTransform(sCTM)
setAttribute(“cx”,mySVGPointTransC.x)
setAttribute(“cy”,mySVGPointTransC.y)
ellipse.setAttribute(“rx”,rx*scaleX)
ellipse.setAttribute(“ry”,ry*scaleY)
//---变换的强制消除--
setAttribute(“transform”、“”)
ellipse.removeAttribute(“变换”)
}
函数screenRect(rect,svg)
{
var sCTM=rect.getCTM()
var scaleX=sCTM.a;
var scaleY=sCTM.d;
var x=parseFloat(rect.getAttribute(“x”))
var y=parseFloat(rect.getAttribute(“y”))
var width=parseFloat(rect.getAttribute(“宽度”))
var height=parseFloat(rect.getAttribute(“height”))
var mySVGPoint=svg.createSVGPoint();
mySVGPoint.x=x
mySVGPoint.y=y
mySVGPointTrans=mySVGPoint.matrixTransform(sCTM)
rect.setAttribute(“x”,mySVGPointTrans.x)
rect.setAttribute(“y”,mySVGPointTrans.y)
rect.setAttribute(“宽度”,宽度*scaleX)
rect.setAttribute(“高度”,高度*scaleY)
//---变换的强制消除--
rect.setAttribute(“transform”,“”)
rect.removeAttribute(“转换”)
}
函数屏幕多段线(myPoly、svg)
{
var sCTM=myPoly.getCTM()
var pointsList=myPoly.points;
var n=pointsList.numberOfItems;
对于(var m=0;m给定:
function simplifyTransform(point,matrix){
simpleX = point.x * matrix[0] + point.y * matrix[2] + matrix[4];
simpleY = point.x * matrix[1] + point.y * matrix[3] + matrix[5];
return({x:simpleX,y:simpleY});
}
- 您未转换的SVG点
- 以及您的SVG转换矩阵
可以从数学上将变换应用于这些点
结果点是变换后的XY——“标准化”XY
生成的点将在与转换的SVG点相同的位置绘制到画布
生成的点不需要在正确的位置绘制SVG转换
下面是应用转换矩阵“规范化”点的代码:
function simplifyTransform(point,matrix){
simpleX = point.x * matrix[0] + point.y * matrix[2] + matrix[4];
simpleY = point.x * matrix[1] + point.y * matrix[3] + matrix[5];
return({x:simpleX,y:simpleY});
}
下面是一个例子:
下面是代码和演示:
正文{背景色:象牙;}
#画布{边框:1px纯红;}
$(函数(){
var canvas=document.getElementById(“canvas”);
var ctx=canvas.getContext(“2d”);
var x=50;
变量y=50;
var h=30;
var w=50;
var矩阵=[1.25,75,75,1.25,20,20];
ctx.save();
变换(矩阵[0],矩阵[1],矩阵[2],矩阵[3],矩阵[4],矩阵[5],矩阵[6]);
ctx.fillStyle=“红色”;
ctx.fillRect(x,y,w,h);
ctx.restore();
//将矩形的4个角做成一个数组
var点=[];
push({x:x,y:y});
push({x:x+w,y:y});
push({x:x+w,y:y+h});
push({x:x,y:y+h});
//获取未转换空间中已转换矩形的角点
var rect=简化多边形(点、矩阵);
//笔划未转换的矩形
ctx.save();
ctx.strokeStyle=“绿色”;
ctx.线宽=2;
移动到(rect[0].x,rect[0].y);
对于(var i=1;
function simplifyTransform(point,matrix){
simpleX = point.x * matrix[0] + point.y * matrix[2] + matrix[4];
simpleY = point.x * matrix[1] + point.y * matrix[3] + matrix[5];
return({x:simpleX,y:simpleY});
}
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
#canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var x=50;
var y=50;
var h=30;
var w=50;
var matrix=[1.25,.75,.75,1.25,20,20];
ctx.save();
ctx.transform(matrix[0],matrix[1],matrix[2],matrix[3],matrix[4],matrix[5],matrix[6]);
ctx.fillStyle="red";
ctx.fillRect(x,y,w,h);
ctx.restore();
// make an array of the 4 corners of the rectangle
var points=[];
points.push({x:x,y:y});
points.push({x:x+w,y:y});
points.push({x:x+w,y:y+h});
points.push({x:x,y:y+h});
// get the transformed rectangle's corners in untransformed space
var rect=simplifyPoly(points,matrix);
// stroke the untransformed rectangle
ctx.save();
ctx.strokeStyle="green";
ctx.lineWidth=2;
ctx.moveTo(rect[0].x,rect[0].y);
for(var i=1;i<rect.length;i++){
ctx.lineTo(rect[i].x,rect[i].y);
}
ctx.closePath();
ctx.stroke();
ctx.restore();
function simplifyTransform(point,matrix){
simpleX = point.x * matrix[0] + point.y * matrix[2] + matrix[4];
simpleY = point.x * matrix[1] + point.y * matrix[3] + matrix[5];
return({x:simpleX,y:simpleY});
}
function simplifyPoly(points,matrix){
var simplePoints=[];
for(var i=0;i<points.length;i++){
simplePoints.push(simplifyTransform(points[i],matrix));
}
return(simplePoints);
}
}); // end $(function(){});
</script>
</head>
<body>
<h4>The red fill is drawn using untransformed points plus a transform<br>The green stroke is drawn using the "simplified" points--no transform involved.</h4>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>