How do you load and display SVG graphics in three.js? - svg

Consider, I have an SVG vector graphics file (logotype), which I want to load and display in three.js (with WebGL renderer).
What would be the recommended way to approach this?
It seems like I need to load the image and to create a geometry and a mesh from it.
I've managed to load the SVG document using the THREE.SVGLoader, but I can't find any relevant information on how to create a geometry/mesh from it further down the line.
function preload () {
const svgLoader = new THREE.SVGLoader();
svgLoader.load('images/logo.svg', svgDocument => {
// #todo: create a geometry/mesh from svgDocument?
// #todo: scene.add(logoMesh);
});
}

Texture
If you need svg only for texture purposes:
Render svg image to canvas
use that canvas as source of texture
use texture in your scene...
Disclaimer I'm not the author of this code, I just fixed jsfiddle that I've found
window.onload = () => {
var mesh;
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(50, 500 / 400, 0.1, 1000);
camera.position.z = 10;
var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(500, 400);
document.body.appendChild(renderer.domElement);
var svg = document.getElementById("svgContainer").querySelector("svg");
var svgData = (new XMLSerializer()).serializeToString(svg);
var canvas = document.createElement("canvas");
var svgSize = svg.getBoundingClientRect();
canvas.width = svgSize.width;
canvas.height = svgSize.height;
var ctx = canvas.getContext("2d");
var img = document.createElement("img");
img.setAttribute("src", "data:image/svg+xml;base64," + window.btoa(unescape(encodeURIComponent(svgData))) );
img.onload = function() {
ctx.drawImage(img, 0, 0);
var texture = new THREE.Texture(canvas);
texture.needsUpdate = true;
var geometry = new THREE.SphereGeometry(3, 50, 50, 0, Math.PI * 2, 0, Math.PI * 2);
var material = new THREE.MeshBasicMaterial({ map: texture });
material.map.minFilter = THREE.LinearFilter;
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
};
var render = function () {
requestAnimationFrame(render);
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
};
render();
}
<script src="https://threejs.org/build/three.min.js"></script>
<div id="svgContainer" style="width: 222px; height: 222px;">
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" version="1.1">
<rect width="200" height="200" fill="lime" stroke-width="4" stroke="pink" />
<circle cx="125" cy="125" r="75" fill="orange" />
<polyline points="50,150 50,200 200,200 200,100" stroke="red" stroke-width="4" fill="none" />
<line x1="50" y1="50" x2="200" y2="200" stroke="blue" stroke-width="4" />
</svg>
</div>
Mesh
If you would like to render svg as geometry I'll would suggest use of some libraries e.g. svg-mesh-3d
Example from docs of svg-mesh-3d
var loadSvg = require('load-svg')
var parsePath = require('extract-svg-path').parse
var svgMesh3d = require('svg-mesh-3d')
loadSvg('svg/logo.svg', function (err, svg) {
if (err) throw err
var svgPath = parsePath(svg)
var mesh = svgMesh3d(svgPath, {
delaunay: false,
scale: 4
})
})
Blender
Alternative options is to use blender to import svg, (optionally) tune geometry and export it to Three.js using Three.js Blender Export

Related

How to drag svgs inserted by button click?

What I'm trying to do is insert svg circles by clicking button to the workspace. Beside that, I want to free drag all those circles.
Can you help me the code?
document.getElementById('draw').addEventListener('click', function(){
document.getElementById('here').innerHTML =
'<svg height="100" width="100">' +
'<circle cx="50" cy="50" r="40" stroke="black" stroke-width="1" fill="rgba(130,130,130,0.6)">' +
'</svg>';
});
<button id="draw">Draw Circle</button>
<div id="here"></div>
I was amazed that creating an SVG like this would work, and it works! (on IE too). However it creates problems when trying to work with events. I prefer to create the SVG element and the circle element using createElementNS and use appendChild to append them to the DOM
const SVG_NS = 'http://www.w3.org/2000/svg';
const SVG_XLINK = "http://www.w3.org/1999/xlink";
/*let innerSVG = '<svg height="100" width="100">' +
'<circle cx="50" cy="50" r="40" stroke="black" stroke-width="1" fill="rgba(130,130,130,0.6)">' +
'</svg>';*/
let svgdata = {width:100,height:100}
let circledata = {cx:50,cy:50,r:40}
// creating a new SVG element using the data
let svg = newSVG(svgdata);
// creating a new circle element using the data and appending it to the svg
let circle = drawCircle(circledata, svg);
// the offset between the click point on the SVG and the left upper corner of the SVG
let offset={}
// a flag to control the dragging
let dragging = false;
// the mouse position
let m;
document.getElementById('draw').addEventListener('click', function(){
here.appendChild(svg)});
// events
here.addEventListener("mousedown",(evt)=>{
dragging = true;
offset = oMousePos(svg, evt);
})
here.addEventListener("mousemove",(evt)=>{
if(dragging){
m = oMousePos(here, evt);
svg.style.top = (m.y - offset.y)+"px";
svg.style.left = (m.x - offset.x)+"px";
}
})
here.addEventListener("mouseup",(evt)=>{
dragging = false;
})
function drawCircle(o, parent) {
var circle = document.createElementNS(SVG_NS, 'circle');
for (var name in o) {
if (o.hasOwnProperty(name)) {
circle.setAttributeNS(null, name, o[name]);
}
}
parent.appendChild(circle);
return circle;
}
function newSVG(o) {
let svg = document.createElementNS(SVG_NS, 'svg');
for (var name in o) {
if (o.hasOwnProperty(name)) {
svg.setAttributeNS(null, name, o[name]);
}
}
return svg;
}
function oMousePos(elmt, evt) {
let ClientRect = elmt.getBoundingClientRect();
return {
x: Math.round(evt.clientX - ClientRect.left),
y: Math.round(evt.clientY - ClientRect.top)
}
}
svg{border:1px solid;position:absolute;}
circle{
stroke:black;stroke-width:1;fill:rgba(130,130,130,0.6);
}
#here{width:100%; height:100vh; background-color:#efefef;margin:0; padding:0; position:relative}
<button id="draw">Draw Circle</button>
<div id="here"></div>

Why don't these adjacent SVG paths join cleanly?

There's a line between these paths; why?
(On my machine it looks like this: )
path.myshape {
stroke: gray;
fill: gray;
stroke-opacity:0.5;
fill-opacity:0.5;
}
<svg width="120px" height="120px" viewBox="0 0 120 120">
<path class="myshape" d="M0 0 L100 100 L100 0" />
<path class="myshape" d="M0 0 L100 100 L0 100" />
</svg>
A similar issue happens even without the stroke (it's harder to see but it's still there). I am confused why this is happening; if I have two triangles that are halves of a square, why don't I just see a square?
Is there a way to prevent this?
(On my machine it looks like this: )
path.myshape {
stroke: none;
fill: gray;
fill-opacity:0.5;
}
<svg width="120px" height="120px" viewBox="0 0 120 120">
<path class="myshape" d="M0 0 L100 100 L100 0" />
<path class="myshape" d="M0 0 L100 100 L0 100" />
</svg>
More realistic example (where I'm trying to get rid of the lines between triangles that have nearly the same fill/stroke attributes):
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 500 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// add the graph canvas to the body of the webpage
var svg = d3.select("div#plot1").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
var axis = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var xsc = d3.scaleLinear()
.domain([-2, 2]) // the range of the values to plot
.range([ 0, width ]); // the pixel range of the x-axis
var ysc = d3.scaleLinear()
.domain([-2, 2])
.range([ height, 0 ]);
var closedLine = d3.line()
.x(function(d){ return xsc(d[0]); })
.y(function(d){ return ysc(d[1]); })
.curve(d3.curveLinearClosed);
function attrfunc(f,attr) {
return function(d) {
return f(d[attr]);
};
}
function doit(data)
{
var items = axis.selectAll("path.item")
.data(data);
items.enter()
.append("path")
.attr("class", "item")
.merge(items)
.attr("d", attrfunc(closedLine, "xy"))
.attr("stroke", "gray")
.attr("stroke-width", 1)
.attr("stroke-opacity", function(d) { return 1-d.age;})
.attr("fill", "gray")
.attr("fill-opacity", function(d) {return 1-d.age;});
items.exit().remove();
}
var state = {
t: 0,
theta: 0,
omega: 0.5,
A: 1.0,
N: 60,
history: []
}
d3.timer(function(elapsed)
{
var S = state;
if (S.history.length > S.N)
S.history.shift();
var dt = Math.min(0.1, elapsed*1e-3);
S.t += dt;
S.theta += S.omega * dt;
var sample = {
t: S.t,
x: S.A*(Math.cos(S.theta)+0.1*Math.cos(6*S.theta)),
y: S.A*(Math.sin(S.theta)+0.1*Math.sin(6*S.theta))
}
S.history.push(sample);
// Create triangular regions
var data = [];
for (var k = 0; k < S.history.length-1; ++k)
{
var pt1 = S.history[k];
var pt2 = S.history[k+1];
data.push({age: (S.history.length-1-k)/S.N,
xy:
[[0,0],
[pt1.x,pt1.y],
[pt2.x,pt2.y]]
});
}
doit(data);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.8.0/d3.min.js"></script>
<div id="plot1">
</div>

Drag & Drop functionality lost when fabric.Canvas is initialized

I have this canvas in the HTML and the D&D works fine:
<canvas id="canvas" width="800" height="450" ondragover="onDragOver($event)" ondrop="onDrop($event)"></canvas>
but when I want to create an instance of fabric.js to make use of the API, the D&D functionality is lost.
this.canvasObj = new fabric.Canvas('canvas', {});
How can I preserve the functionality?
The Drag & Drop functionality is lost because, when you create a new instance of fabric.js canvas, it automatically creates a new canvas element (with a class upper-canvas) on top of your original canvas, which obviously doesn't have the drag and drop functionality.
SO, you'll need to add those functionality to the newly created canvas as well.
/* for demonstration */
var ctx = document.getElementById('canvas').getContext('2d');
var text = document.getElementById('text');
function onDragOver(event) {
event.preventDefault();
}
function onDrop(event) {
document.body.removeChild(text);
draw();
}
function draw() {
ctx.clearRect(0, 0, 200, 200)
ctx.font = '14px Verdana'
ctx.fillText(text.innerText, 10, 100);
requestAnimationFrame(draw);
}
/* main part */
var canvasObj = new fabric.Canvas('canvas');
var upper_canvas = document.querySelector('.upper-canvas');
upper_canvas.ondrop = onDrop;
upper_canvas.ondragover = onDragOver;
canvas {
border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.9/fabric.min.js"></script>
<p draggable="true" id="text">Drag me into the canvas!</p>
<canvas id="canvas" width="200" height="200" ondrop="onDrop(event)" ondragover="onDragOver(event)"></canvas>

YES/NO - is there a way to improve mouse dragging with pure SVG tools?

So I was spending some time playing around with pure (no external libraries) SVG elements dragging.
In general all works, but there is this nasty issue for fast moving mouse:
- when user mousedowns a draggable SVG element close to its edge
- then drags (mousemove) such draggable too fast
- the mouse "loses" the draggable
Here the issue is described in more details:
http://www.svgopen.org/2005/papers/AdvancedMouseEventModelForSVG-1/index.html#S3.2
Also here the author tried to fix UX by leveraging mouseout event:
http://nuclearprojects.com/blog/svg-click-and-drag-object-with-mouse-code/
I copied the above code snippet here: http://codepen.io/cmer41k/pen/zNGwpa
The question I have is:
Is there no other way (provided by pure SVG) to prevent such "loss" of SVG element while mouse moves too fast?
My attempt to solve this was:
- detect (somehow) that mouseout event happened without finishing the dragging.
- and if so (we sort of detected "disconnect") - reconnect the SVG element with current mouse position.
Is there a reason why this wouldn't work?
Code:
var click=false; // flag to indicate when shape has been clicked
var clickX, clickY; // stores cursor location upon first click
var moveX=0, moveY=0; // keeps track of overall transformation
var lastMoveX=0, lastMoveY=0; // stores previous transformation (move)
function mouseDown(evt){
evt.preventDefault(); // Needed for Firefox to allow dragging correctly
click=true;
clickX = evt.clientX;
clickY = evt.clientY;
evt.target.setAttribute("fill","green");
}
function move(evt){
evt.preventDefault();
if(click){
moveX = lastMoveX + ( evt.clientX – clickX );
moveY = lastMoveY + ( evt.clientY – clickY );
evt.target.setAttribute("transform", "translate(" + moveX + "," + moveY + ")");
}
}
function endMove(evt){
click=false;
lastMoveX = moveX;
lastMoveY = moveY;
evt.target.setAttribute("fill","gray");
}
The most important part of your code is missing, namely how or more specifically on which element you register the events.
What you basically do to prevent this problem is to register the mousemove and mouseup events on the outermost svg element, and not on the element you want to drag.
svg.addEventListener("mousemove", move)
svg.addEventListener("mouseup", endMove)
When starting the drag, register the events on the svg element, and when done unregister them.
svg.removeEventListener("mousemove", move)
svg.removeListener("mouseup", endMove)
you have to store the element you are currently dragging, so it is available in the other event handlers.
what i additionally do is to set pointer-events to "none" on the dragged
element so that you can react to mouse events underneath the dragged element (f.e. finding the drop target...)
evt.target.setAttribute("pointer-events", "none")
but don't forget to set it back to something sensible when dragging is done
evt.target.setAttribute("pointer-events", "all")
var click = false; // flag to indicate when shape has been clicked
var clickX, clickY; // stores cursor location upon first click
var moveX = 0,
moveY = 0; // keeps track of overall transformation
var lastMoveX = 0,
lastMoveY = 0; // stores previous transformation (move)
var currentTarget = null
function mouseDown(evt) {
evt.preventDefault(); // Needed for Firefox to allow dragging correctly
click = true;
clickX = evt.clientX;
clickY = evt.clientY;
evt.target.setAttribute("fill", "green");
// register move events on outermost SVG Element
currentTarget = evt.target
svg.addEventListener("mousemove", move)
svg.addEventListener("mouseup", endMove)
evt.target.setAttribute("pointer-events", "none")
}
function move(evt) {
evt.preventDefault();
if (click) {
moveX = lastMoveX + (evt.clientX - clickX);
moveY = lastMoveY + (evt.clientY - clickY);
currentTarget.setAttribute("transform", "translate(" + moveX + "," + moveY + ")");
}
}
function endMove(evt) {
click = false;
lastMoveX = moveX;
lastMoveY = moveY;
currentTarget.setAttribute("fill", "gray");
svg.removeEventListener("mousemove", move)
svg.removeEventListener("mouseup", endMove)
currentTarget.setAttribute("pointer-events", "all")
}
<svg id="svg" width="800" height="600" style="border: 1px solid black; background: #E0FFFF;">
<rect x="0" y="0" width="800" height="600" fill="none" pointer-events="all" />
<circle id="mycirc" cx="60" cy="60" r="22" onmousedown="mouseDown(evt)" />
</svg>
more advanced
there are still two things not so well with this code.
it does not work for viewBoxed SVGs nor for elements inside
transformed parents.
all the globals are bad coding practice.
here is how to fix those:
Nr. 1 is solved by converting mouse coordinates into local coordinates using the inverse of getScreenCTM (CTM = Current Transformation Matrix).
function globalToLocalCoords(x, y) {
var p = elem.ownerSVGElement.createSVGPoint()
var m = elem.parentNode.getScreenCTM()
p.x = x
p.y = y
return p.matrixTransform(m.inverse())
}
For nr. 2 see this implementation:
var dre = document.querySelectorAll(".draggable")
for (var i = 0; i < dre.length; i++) {
var o = new Draggable(dre[i])
}
function Draggable(elem) {
this.target = elem
this.clickPoint = this.target.ownerSVGElement.createSVGPoint()
this.lastMove = this.target.ownerSVGElement.createSVGPoint()
this.currentMove = this.target.ownerSVGElement.createSVGPoint()
this.target.addEventListener("mousedown", this)
this.handleEvent = function(evt) {
evt.preventDefault()
this.clickPoint = globalToLocalCoords(evt.clientX, evt.clientY)
this.target.classList.add("dragged")
this.target.setAttribute("pointer-events", "none")
this.target.ownerSVGElement.addEventListener("mousemove", this.move)
this.target.ownerSVGElement.addEventListener("mouseup", this.endMove)
}
this.move = function(evt) {
var p = globalToLocalCoords(evt.clientX, evt.clientY)
this.currentMove.x = this.lastMove.x + (p.x - this.clickPoint.x)
this.currentMove.y = this.lastMove.y + (p.y - this.clickPoint.y)
this.target.setAttribute("transform", "translate(" + this.currentMove.x + "," + this.currentMove.y + ")")
}.bind(this)
this.endMove = function(evt) {
this.lastMove.x = this.currentMove.x
this.lastMove.y = this.currentMove.y
this.target.classList.remove("dragged")
this.target.setAttribute("pointer-events", "all")
this.target.ownerSVGElement.removeEventListener("mousemove", this.move)
this.target.ownerSVGElement.removeEventListener("mouseup", this.endMove)
}.bind(this)
function globalToLocalCoords(x, y) {
var p = elem.ownerSVGElement.createSVGPoint()
var m = elem.parentNode.getScreenCTM()
p.x = x
p.y = y
return p.matrixTransform(m.inverse())
}
}
.dragged {
fill-opacity: 0.5;
stroke-width: 0.5px;
stroke: black;
stroke-dasharray: 1 1;
}
.draggable{cursor:move}
<svg id="svg" viewBox="0 0 800 600" style="border: 1px solid black; background: #E0FFFF;">
<rect x="0" y="0" width="800" height="600" fill="none" pointer-events="all" />
<circle class="draggable" id="mycirc" cx="60" cy="60" r="22" fill="blue" />
<g transform="rotate(45,175,75)">
<rect class="draggable" id="mycirc" x="160" y="60" width="30" height="30" fill="green" />
</g>
<g transform="translate(200 200) scale(2 2)">
<g class="draggable">
<circle cx="0" cy="0" r="30" fill="yellow"/>
<text text-anchor="middle" x="0" y="0" fill="red">I'm draggable</text>
</g>
</g>
</svg>
<div id="out"></div>

SVG - Get untransformed points?

Say I have the following SVG:
<g id="g1" transform="translate(100, 250) rotate(90)" >
<path id="path1" d="M 100,100 c...
Is there a way to get the actual coordinates of the d attribute? Ideally I want some function such as untransform below:
var transform = $("g1").getAttribute("transform");
var d = $("path1").getAttribute("d");
var dUntransformed = untransform(d, transform);
$("g1").removeAttribute("transform");
$("path1").setAttribute("d", dUntransformed);
The idea is that if I ran this script the resulting image would be identical to the previous image.
The reason I want to do this is because I have an animation that follows this path. However because of the transform the animation is off. And if I add the transform to the animateMotion object the animation is still off. So my thought is to remove the path and put it back exactly where it is. So that I can get the animation to work. (The AnimateMotion is similar to this demo: https://mdn.mozillademos.org/files/3261/animateMotion.svg)
Here is an example to return screen points after tranformations : polygon, path, polyline. The path example does not work or arcs. Also, in some cases relative points may not return. This uses getCTM and matrixTransform. It may be possible to create an array to 'remember' the points at various time lines.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Return Screen Points After Tranformations</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body style='padding:0px;font-family:arial'>
<center>
<h4>Return Screen Points After Tranformations : polygon, path, polyline</h4>
<div style='width:90%;background-color:gainsboro;text-align:justify;padding:10px;border-radius:10px;'>
In many cases it is meaningful to return certain svg elements(polygon, polyline, and path) to their screen x,y values following transformations. This is accomplished using <b>getCTM</b>, and <b>matrixTransform</b>
Note: Use vector-effect="non-scaling-stroke" for elements with stroke(*not available in IE).
</div>
<div id="svgDiv" style="background-color:lightgreen;width:500px;height:500px;">
<svg id="mySVG" width="500" height="500">
<path id="myPath" vector-effect="non-scaling-stroke" transform="scale(.8)translate(120 50)skewY(15)rotate(-15)" fill="yellow" stroke="black" stroke-width="2"
d="M50,50 Q-30,100 50,150 100,230 150,150 230,100 150,50 100,-30 50,50"/>
<polyline vector-effect="non-scaling-stroke" id="myPolyline" transform="scale(.3)translate(700 620)" fill="red" stroke="black" stroke-width="3" points="122 60 150 450 500 400" />
<polygon vector-effect="non-scaling-stroke" id="myPolygon" transform="scale(3)translate(122 132)" fill="purple" stroke="white" stroke-width="3"points="15,0 10.6066,-10.6066 9.18486e-016,-15 -10.6066,-10.6066 -15,-1.83697e-015 -10.6066,10.6066 -2.75545e-015,15 10.6066,10.6066" />
</svg>
</div>
<button onClick=change2Screen()>change to screen values</button>
<br />SVG Source:<br />
<textarea id=mySVGValue style='font-size:120%;font-family:lucida console;width:90%;height:200px'></textarea>
<br />Javascript:<br />
<textarea id=jsValue style='border-radius:26px;font-size:110%;font-weight:bold;color:midnightblue;padding:16px;background-color:beige;border-width:0px;font-size:100%;font-family:lucida console;width:90%;height:400px'></textarea>
</center>
<div id='browserDiv' style='padding:3px;position:absolute;top:5px;left:5px;background-color:gainsboro;'></div>
<script id=myScript>
//--button---
function change2Screen()
{
screenPolyline(myPolyline)
screenPolygon(myPolygon)
screenPath(myPath)
mySVGValue.value=svgDiv.innerHTML
}
function screenPolyline(myPoly)
{
var sCTM = myPoly.getCTM()
var svgRoot = myPoly.ownerSVGElement
var pointsList = myPoly.points;
var n = pointsList.numberOfItems;
for(var m=0;m<n;m++)
{
var mySVGPoint = svgRoot.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")
}
//---except arc/relative paths---
function screenPath(path)
{
var sCTM = path.getCTM()
var svgRoot = path.ownerSVGElement
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 = svgRoot.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 = svgRoot.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 = svgRoot.createSVGPoint();
mySVGPoint2.x = segObj.x2
mySVGPoint2.y = segObj.y2
mySVGPointTrans2 = mySVGPoint2.matrixTransform(sCTM)
segObj.x2=mySVGPointTrans2.x
segObj.y2=mySVGPointTrans2.y
}
}
//---force removal of transform--
path.setAttribute("transform","")
path.removeAttribute("transform")
}
//---changes all transformed points to screen points---
function screenPolygon(myPoly)
{
var sCTM = myPoly.getCTM()
var svgRoot = myPoly.ownerSVGElement
var pointsList = myPoly.points;
var n = pointsList.numberOfItems;
for(var m=0;m<n;m++)
{
var mySVGPoint = svgRoot.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","")
}
</script>
<script>
document.addEventListener("onload",init(),false)
function init()
{
mySVGValue.value=svgDiv.innerHTML
jsValue.value=myScript.text
}
</script>
</body>
</html>

Resources