I want to create/draw paths (lines) in a SVG using Javascript. But for some reason the lines don't show, even though the html is generated. Is there something i am missing, can you have a look at my code and tell me why it doesn't show?
This is mz JS code
//add lines from layerborderbot to ldescborderbot
var _Ldesc = document.createElement('svg');
_Ldesc.style.cssText = `position:absolute;left:calc(26vw + 3px);top:calc(66mm + 2px);width:calc(2.1vw + 1px);height:${scaleLength(Math.ceil(layerTotalLengthN)*100)}cm;`;
for (x = 0; layer_anzahl > x; x++) {
var _lineLdesc = document.createElementNS("http://www.w3.org/2000/svg", 'path'); //Create a path in SVG's namespace
var tempPos; var tempHeight; var tY; var tH;
if(typeof positionLith[x+1] === 'undefined' && dHdesc[x] < 0) {tY = cm2px(parseFloat(scaleLength(layerTotalLengthN*100))); tH = cm2px(dHdesc[x]);}
else { tY = cm2px(scaleLength(parseFloat(lith_to[x+1])*100));}
if(dHdesc[x] > 0) { tY = cm2px(scaleLength(parseFloat(lith_to[x])*100)); tH = cm2px(getlayersize(x));}
else { if (x==0 && dHdesc[0]<0) { tH = cm2px(realHeightLdesc[x] - getlayersize(x));}
else if (x==0 && dHdesc[0]>0) { tH = cm2px(getlayersize(x));}
else {
if(occupyDesc[x] > 0) { tH = cm2px(occupyDesc[x]-getlayersize(x));}
else { tH = cm2px(realHeightLdesc[x]-getlayersize(x));}
}
}
_lineLdesc.setAttribute("d",`M 0 ${tY} L ${vw2px(2.1)} ${tH}`); //Set path's data
_lineLdesc.style.stroke = "#000"; //Set stroke colour
_lineLdesc.style.strokeWidth = "1"; //Set stroke width
_Ldesc.appendChild(_lineLdesc);
This is the HTML output (from chrome console)
<svg style="position: absolute; left: calc(26vw + 3px); top: calc(251.449px); width: calc(2.1vw + 1px); height: 12cm;">
<path d="M 0 151.18110426684856 L 33 151.18110426684856" style="stroke: rgb(0, 0, 0); stroke-width: 1;"></path>
<path d="M 0 434.64567476718963 L 33 15.807083450280626" style="stroke: rgb(0, 0, 0); stroke-width: 1;"></path>
<path d="M 0 434.64567476718963 L 33 226.77165640027278" style="stroke: rgb(0, 0, 0); stroke-width: 1;"></path>
</svg>
You don't specify a viewBox, so it defaults to 300x150.
Yet the 3 Lines you draw require a viewBox="0 0 34 435" to show all of those Lines:
<style>
svg{
height:180px;
background:pink;
}
</style>
<svg viewBox="0 0 34 435" stroke-width="3">
<path d="M 0 151.1 L 33 151.1" stroke="blue"></path>
<path d="M 0 434.6 L 33 15.8" stroke="red"></path>
<path d="M 0 434.6 L 33 226.7" stroke="green"></path>
</svg>
Related
I have to adjust a SVG's position and scale using DIV having handles.
Everything is working as expected except SVG is jumping the first time at the time of dragging the div handles. Only the SVG is jumping.
See here that the class "selection" is a DIV controlling the selected SVG with attribute ("[selection=true]")
$( ".selector" ).resizable({
aspectRatio: false,
handles: {
'nw': '#nwgrip',
'ne': '#negrip',
'sw': '#swgrip',
'se': '#segrip' },
resize: function(event, ui) {
console.log(ui.size.width);
$('#posW').text('Width: ' + Math.round(ui.size.width) );
$('#posH').text('Height: ' + Math.round(ui.size.height) );
$("[selection=true]").attr("width", Math.round(ui.size.width) );
$("[selection=true]").attr("height", Math.round(ui.size.height) );
$("[selection=true]").attr("x", Math.round(ui.position.left) );
$("[selection=true]").attr("y", Math.round(ui.position.top) );
}
}).draggable({
drag: function(event, ui) {
var offset = $(this).offset();
var xPos = offset.left;
var yPos = offset.top;
$("[selection=true]").attr("x", Math.round(xPos) );
$("[selection=true]").attr("y", Math.round(yPos) );
$('#posX').text('x: ' + xPos);
$('#posY').text('y: ' + yPos);
}
}
);
Please check jsfiddle link
Is this a bug that can be fixed?
Here's a working version of your original. It handles all clicking, dragging, and selector box behaviour within the "canvas" SVG.
It uses pure JS and manipulates the badge <svg> and selector box elements using DOM methods.
Hopefully it is fairly easily to follow what is going on.
let selectedBadge = null;
let isDraggingRect = null;
let isDraggingHandle = null;
let dragOffsetX = 0;
let dragOffsetY = 0;
// Event handlers for the badges
let badges = document.querySelectorAll(".canvas > .badge");
badges.forEach(b => b.addEventListener("click", select));
// Event handlers for selector box and handles
let selectorRect = document.querySelector("#selector rect");
selectorRect.addEventListener("mousedown", selectorMouseDown);
let handleNW = document.getElementById("nwgrip");
let handleNE = document.getElementById("negrip");
let handleSW = document.getElementById("swgrip");
let handleSE = document.getElementById("segrip");
let grips = document.querySelectorAll("#selector > circle");
grips.forEach(g => {
g.addEventListener("mousedown", gripMouseDown);
});
// Attach mousemove and mouseup events to SVG for dragging purposes
// We attach to the parent SVG because mouse events on small elements
// will be missed if you move the mouse outside the element.
let canvasSVG = document.querySelector("#svg_obj > .canvas");
canvasSVG.addEventListener("mousemove", mouseMove);
canvasSVG.addEventListener("mouseup", mouseUp);
// select a badge
function select(evt) {
hideSelector(selectedBadge);
selectedBadge = evt.target.ownerSVGElement;
showSelector(selectedBadge)
}
function showSelector(badge) {
setSelectorDimensionsTo({x: badge.x.baseVal.value,
y: badge.y.baseVal.value,
width: badge.width.baseVal.value,
height: badge.height.baseVal.value});
document.getElementById("selector").classList.add("show");
}
function hideSelector(badge) {
if (selectedBadge) {
document.getElementById("selector").classList.remove("show");
selectedBadge = null;
}
}
function setSelectorDimensionsTo(bounds) {
selectorRect.x.baseVal.value = bounds.x;
selectorRect.y.baseVal.value = bounds.y;
selectorRect.width.baseVal.value = bounds.width;
selectorRect.height.baseVal.value = bounds.height;
handleNW.cx.baseVal.value = bounds.x;
handleNW.cy.baseVal.value = bounds.y;
handleNE.cx.baseVal.value = bounds.x + bounds.width;
handleNE.cy.baseVal.value = bounds.y;
handleSW.cx.baseVal.value = bounds.x;
handleSW.cy.baseVal.value = bounds.y + bounds.height;
handleSE.cx.baseVal.value = bounds.x + bounds.width;
handleSE.cy.baseVal.value = bounds.y + bounds.height;
}
function moveSelectorTo(x, y) {
selectorRect.x.baseVal.value = x;
selectorRect.y.baseVal.value = y;
let w = selectorRect.width.baseVal.value;
let h = selectorRect.height.baseVal.value;
handleNW.cx.baseVal.value = x;
handleNW.cy.baseVal.value = y;
handleNE.cx.baseVal.value = x + w;
handleNE.cy.baseVal.value = y;
handleSW.cx.baseVal.value = x;
handleSW.cy.baseVal.value = y + h;
handleSE.cx.baseVal.value = x + w;
handleSE.cy.baseVal.value = y + h;
}
function moveSelectedBadgeTo(x, y) {
selectedBadge.x.baseVal.value = x;
selectedBadge.y.baseVal.value = y;
}
function selectorMouseDown(evt) {
isDraggingRect = selectedBadge;
let mousePos = mouseCoordsToSVGCoords(evt.offsetX, evt.offsetY);
dragOffsetX = mousePos.x - selectedBadge.x.baseVal.value;
dragOffsetY = mousePos.y - selectedBadge.y.baseVal.value;
}
function mouseUp(evt) {
isDraggingRect = null;
isDraggingHandle = null;
}
// Handles both:
// - dragging selector rect
// - dragging selector grip/handle
function mouseMove(evt) {
if (isDraggingRect)
{
// Move selector
let mousePos = mouseCoordsToSVGCoords(evt.offsetX, evt.offsetY);
moveSelectorTo(mousePos.x - dragOffsetX, mousePos.y - dragOffsetY);
// Move badge
moveSelectedBadgeTo(mousePos.x - dragOffsetX, mousePos.y - dragOffsetY);
}
else if (isDraggingHandle)
{
gripMouseMove(evt);
}
}
// Convert page mouse coords to SVG coords.
// Takes into account any scaling due to the presence of a viewBox.
function mouseCoordsToSVGCoords(mouseX, mouseY) {
var pt = canvasSVG.createSVGPoint();
pt.x = mouseX;
pt.y = mouseY;
return pt.matrixTransform(canvasSVG.getScreenCTM().inverse());
}
function gripMouseDown(evt) {
isDraggingHandle = evt.target;
let mousePos = mouseCoordsToSVGCoords(evt.offsetX, evt.offsetY);
dragOffsetX = mousePos.x - isDraggingHandle.cx.baseVal.value;
dragOffsetY = mousePos.y - isDraggingHandle.cy.baseVal.value;
}
function gripMouseUp(evt) {
isDraggingHandle = null;
}
function gripMouseMove(evt) {
// Move handle thus resizing selector
let mousePos = mouseCoordsToSVGCoords(evt.offsetX, evt.offsetY);
mousePos.x -= dragOffsetX;
mousePos.y -= dragOffsetY;
let bounds = {};
let oldX = selectorRect.x.baseVal.value;
let oldY = selectorRect.y.baseVal.value;
let oldW = selectorRect.width.baseVal.value;
let oldH = selectorRect.height.baseVal.value;
switch (isDraggingHandle.id) {
case "nwgrip":
bounds = {x: mousePos.x, y: mousePos.y, width: oldX + oldW - mousePos.x, height: oldY + oldH - mousePos.y};
break;
case "negrip":
bounds = {x: oldX, y: mousePos.y, width: mousePos.x - oldX, height: oldY + oldH - mousePos.y};
break;
case "swgrip":
bounds = {x: mousePos.x, y: oldY, width: oldX + oldW - mousePos.x, height: mousePos.y - oldY};
break;
case "segrip":
bounds = {x: oldX, y: oldY, width: mousePos.x - oldX, height: mousePos.y - oldY};
break;
}
setSelectorDimensionsTo(bounds);
// Resize badge
resizeBadgeTo(bounds);
}
function resizeBadgeTo(bounds) {
selectedBadge.x.baseVal.value = bounds.x;
selectedBadge.y.baseVal.value = bounds.y;
selectedBadge.width.baseVal.value = bounds.width;
selectedBadge.height.baseVal.value = bounds.height;
}
.canvas {
background-color: #cecece;
border: 2px solid #cecece;
width: 400px;
height: 400px;
position: relative;
}
#svg_obj {
position: absolute;
width: 100px;
height: 100px;
background: yellow;
}
#selector {
display: none;
}
#selector.show {
display: block;
}
#selector rect {
fill: transparent;
stroke: #f50;
stroke-width: 1px;
}
#nwgrip, #negrip, #swgrip, #segrip, #ngrip, #egrip, #sgrip, #wgrip {
fill: #ffffff;
stroke: #000000;
stroke-width: 1px;
}
<div id='svg_obj'>
<svg class="canvas" viewBox="0 0 400 400" width="400" height="400" >
<svg class="badge" width="200" height="200" viewBox="0 0 400 400">
<g>
<polygon fill="#21574B" points="342.6,0 324.1,19.8 324.1,294.2 302.3,308.3 200,374.1 97.7,308.3 75.8,294.2 57.3,308.3 200,400
342.6,308.3 "/>
<polygon fill="#578677" points="342.6,0 324.1,19.8 75.8,19.8 75.8,294.2 57.3,308.3 57.3,0 "/>
<polygon fill="#8CB2B0" points="324.1,19.8 324.1,294.2 302.3,308.3 200,374.1 97.7,308.3 75.8,294.2 75.8,19.8 "/>
</g>
</svg>
<svg class="badge" width="200" height="200" viewBox="0 0 400 400">
<g>
<polygon fill="#F1F74B" points="342.6,0 324.1,19.8 324.1,294.2 302.3,308.3 200,374.1 97.7,308.3 75.8,294.2 57.3,308.3 200,400
342.6,308.3 "/>
<polygon fill="#578677" points="342.6,0 324.1,19.8 75.8,19.8 75.8,294.2 57.3,308.3 57.3,0 "/>
<polygon fill="#8CB2B0" points="324.1,19.8 324.1,294.2 302.3,308.3 200,374.1 97.7,308.3 75.8,294.2 75.8,19.8 "/>
</g>
</svg>
<svg class="badge" width="200" height="200" viewBox="0 0 400 400">
<g>
<polygon fill="#81579B" points="342.6,0 324.1,19.8 324.1,294.2 302.3,308.3 200,374.1 97.7,308.3 75.8,294.2 57.3,308.3 200,400
342.6,308.3 "/>
<polygon fill="#578677" points="342.6,0 324.1,19.8 75.8,19.8 75.8,294.2 57.3,308.3 57.3,0 "/>
<polygon fill="#8CB2B0" points="324.1,19.8 324.1,294.2 302.3,308.3 200,374.1 97.7,308.3 75.8,294.2 75.8,19.8 "/>
</g>
</svg>
<g id="selector">
<rect width="20" height="20"/>
<circle cx="0" cy="0" r="5" id="nwgrip"/>
<circle cx="20" cy="0" r="5" id="negrip"/>
<circle cx="0" cy="20" r="5" id="swgrip"/>
<circle cx="20" cy="20" r="5" id="segrip"/>
</g>
</svg>
</div>
I have a SVG container (Canvas), which has an SVG path (leftLeg) in it. When I drag the SVG path into another div (save), the path goes somewhere else and doesnt hold the position where I dragged it? How Can I solve this? I am using the following libraries:
http://svgdiscovery.com/SVGjs/Plugins/svg.draggable.js
http://svgdiscovery.com/SVGjs/Plugins/svg.connectable.js
I have the following code:
<style>
#canvas {
overflow: hidden;
background-color: #cccccc;
}
<svg id = "canvas" width="100%" height="100%" viewBox="0 0 400 400" z-index="100">
<svg id="dropzone" pointer-events="all" overflow="visible" width="400" height="350" x="90" y="10" fill="white">
<text x="102" y="-2" font-family="sans-serif" font-size="5px" font-weight="bold" fill="black">Drop here</text>
<rect id="dropzoneBox" x="100" y="0" width="50%" height="50%" stroke="black" stroke-dasharray="3"></rect>
</svg>
<svg id = "save" x="190" y="10" width="200" height="175" overflow="visible">
<rect width="100%" height="100%" fill="red" fill-opacity="0" />
</svg>
</svg>
var canvas = SVG('canvas');
save = SVG('save');
function dragIntoBoard(event) {
console.log(event);
//http://svgjs.dev/referencing/#circular-reference
var node = event.target,
svg = node.instance;
var e = event.detail.event,
posX = e.clientX,
posY = e.clientY,
box = save.node.getBoundingClientRect();
//If the element is dropped on top of #save,
//we move the element from the #canvas wrapper into #save:
if( (box.left <= posX) && (posX <= box.right) &&
(box.top <= posY) && (posY <= box.bottom) ) {
save.add(svg);
//Make the circle's position relative to #save, not #canvas:
svg.cx(svg.cx() - save.x());
svg.cy(svg.cy() - save.y());
//No need to listen for more dragging:
svg.off('dragend.namespace');
}
}
function leftLeg()
{
var lines = canvas.group();
lines.attr({"stroke-width":1})
var markers = canvas.group();
var nodes = canvas.group();
var g1 = nodes.group().translate(50, 100).draggable();
g1.circle(1.5).fill("#000");
var g2 = nodes.group().translate(50, 120).draggable();
g2.circle(1.5).fill("#000");
var g3 = nodes.group().translate(50, 140).draggable();
g3.circle(1.5).fill("#000");
g1.connectable({ //---main, central element---
container: lines,
markers: markers
}, g2).setLineColor("#000");
g2.connectable({
}, g3).setLineColor("#000")
var group = canvas.group()
group.add(lines)
group.add(g1)
group.add(g2)
group.add(g3)
group.draggable();
group.on('dragend.namespace', dragIntoBoard);
}
I got HTML classes like
<path class="paths" fill="gainsboro" d="M644 1780c13...>
<path class="paths" fill="#E5E6E5" d="M759 2308c12,-10...>
<path class="paths" fill="#E0F3EC" d="M1340 1848c-3,9 5,6...>
CSS default value
.paths {display:none;}
JS
window.onload="show()";
function show(){
var a = document.querySelectorAll(".paths");
for(var i=0; i<a.length;i++){
a[i].style.display="";
}
}
With javascript I am trying to unhide all elements one by one to create animation. As you can see, my js code doesn't work and after few hours of trying a decided to ask because I am lost.
EDIT: I forgot to append my project -> https://codepen.io/r8w9/pen/ZxePML
This is what I would do:
add the onload function as an anonymous function, because it doesn't
need a name
put the elements in a real array to have access to
.shift()
set an interval to perform the unhiding on a timed basis
inside the timed function: remove and get the first element from the
array using .shift()
set the elements display to initial(it's
default, because it could be other than block)
if the array is
empty remove the interval
window.onload = function() {
var paths = document.querySelectorAll(".paths");
var hidden = [];
for (var i = 0; i < paths.length; i++) hidden.push(paths[i]);
var interval = setInterval(() => {
hidden.shift().style.display = "initial";
if (hidden.length == 0) clearInterval(interval);
}, 200);
}
.paths {
display: none;
}
<span class="paths">A</span><span class="paths">A</span><span class="paths">A</span><span class="paths">A</span>
(I used <span>, so something is visibly happening)
EDIT For older browsers (without arrow functions support):
var hidden = [];
var interval;
window.onload = function() {
var paths = document.querySelectorAll(".paths");
for (var i = 0; i < paths.length; i++) hidden.push(paths[i]);
interval = setInterval(function() {
hidden.shift().style.display = "initial";
if (hidden.length == 0) clearInterval(interval);
}, 200);
}
.paths {
display: none;
}
<span class="paths">A</span><span class="paths">A</span><span class="paths">A</span><span class="paths">A</span>
window.onload=show();
function show(){
var a = document.querySelectorAll(".paths");
for(var i=0; i<a.length;i++){
a[i].classList.remove("paths");
}
}
.paths {display:none;}
Because class still exist in <path> element that's why it's not show <path> content. Best approach is to remove class to show <path>
<path class="paths" fill="gainsboro" d="M644 1780c13...">a</path>
<path class="paths" fill="#E5E6E5" d="M759 2308c12,-10...">b</path>
<path class="paths" fill="#E0F3EC" d="M1340 1848c-3,9 5,6...">c</path>
Hope this will also helps you.
var elements = document.getElementsByClassName("paths");
console.log(elements)
for (var i = 0, len = elements.length; i < len; i++) {
(function(i){
window.setTimeout(function(){
elements[i].style.display="block";
}, i * 300);
}(i));
}
.paths {
display:none;
}
<svg height="400" width="450">
<path class="paths" id="lineAB" d="M 100 350 l 150 -300" stroke="red" stroke-width="3" fill="none" />
<path class="paths" id="lineBC" d="M 250 50 l 150 300" stroke="red" stroke-width="3" fill="none" />
<path class="paths" d="M 175 200 l 150 0" stroke="green" stroke-width="3" fill="none" />
<path class="paths" d="M 100 350 q 150 -300 300 0" stroke="blue" stroke-width="5" fill="none" />
</svg>
I'm trying to make a basic landing page which randomises the background colour each time the page loads and also changes each time you click on the svg icon.
This is working okay so far, however is it possible to also randomise the colour of the icon rather than it just being white? I'm having trouble integrating the colour property of the svg into the javascript. Here is the code I'm currently using:
$(function() {
var randomColor = Math.floor(Math.random() * 16777215).toString(16);
$("body").css({
backgroundColor: '#' + randomColor
});
$("#colorcode").text("#" + randomColor);
});
var safeColors = ['00', '33', '66', '99', 'cc', 'ff'];
var rand = function() {
return Math.floor(Math.random() * 6);
};
var randomColor = function() {
var r = safeColors[rand()];
var g = safeColors[rand()];
var b = safeColors[rand()];
return "#" + r + g + b;
};
$("body").css({
backgroundColor: '#' + randomColor
});
$(document).ready(function() {
$('#Layer_1').click(function() {
$('body').each(function() {
$(this).css('background', randomColor());
});
});
});
.cls-1 {
fill: #fff;
}
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js">
</script>
<div style="width:400px; position:absolute; left:50%; top:50%; margin:-200px 0 0 -200px; cursor: pointer">
<svg data-name="Layer 1" id="Layer_1" viewbox="0 0 400 400" xmlns="http://www.w3.org/2000/svg">
<title>Artboard 1</title>
<polygon class="cls-1" points="276 124 276 0 124 0 124 124 0 124 0 276 124 276 124 400 276 400 276 276 400 276 400 124 276 124"></polygon>
</svg>
Many thanks for your help. I'm quite new to Javascript so this is a bit of a learning curve for me.
You can change the color of svg by applying the fill CSS property to the svg element (in your case, the polygon)
$('#Layer_1 polygon').css('fill', randomColor());
$(function() {
var randomColor = Math.floor(Math.random() * 16777215).toString(16);
$("body").css({
backgroundColor: '#' + randomColor
});
$("#colorcode").text("#" + randomColor);
});
var safeColors = ['00', '33', '66', '99', 'cc', 'ff'];
var rand = function() {
return Math.floor(Math.random() * 6);
};
var randomColor = function() {
var r = safeColors[rand()];
var g = safeColors[rand()];
var b = safeColors[rand()];
return "#" + r + g + b;
};
$("body").css({
backgroundColor: '#' + randomColor
});
$(document).ready(function() {
$('#Layer_1').click(function() {
$('body').css('background', randomColor());
$('#Layer_1 polygon').css('fill', randomColor());
});
});
#svgdiv {
width: 400px;
position: absolute;
left: 50%;
top: 50%;
margin: -200px 0 0 -200px;
cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="svgdiv">
<svg data-name="Layer 1" id="Layer_1" viewbox="0 0 400 400" xmlns="http://www.w3.org/2000/svg">
<polygon class="cls-1" points="276 124 276 0 124 0 124 124 0 124 0 276 124 276 124 400 276 400 276 276 400 276 400 124 276 124"></polygon>
</svg>
</div>
Sure, you Jquery can be simplified too.
just need to change the fill of.cls-1
var safeColors = ['00', '33', '66', '99', 'cc', 'ff'];
var rand = function() {
return Math.floor(Math.random() * 6);
};
var randomColor = function() {
var r = safeColors[rand()];
var g = safeColors[rand()];
var b = safeColors[rand()];
return "#" + r + g + b;
};
$(document).ready(function() {
$('.cls-1').css('fill', randomColor());
$('body').css('background', randomColor());
$('#Layer_1').click(function() {
$('.cls-1').css('fill', randomColor());
$('body').css('background', randomColor());
});
});
.cross {
width: 400px;
position: absolute;
left: 50%;
top: 50%;
margin: -200px 0 0 -200px;
cursor: pointer;
}
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js">
</script>
<div class="cross">
<svg data-name="Layer 1" id="Layer_1" viewbox="0 0 400 400" xmlns="http://www.w3.org/2000/svg">
<title>Artboard 1</title>
<polygon class="cls-1" points="276 124 276 0 124 0 124 124 0 124 0 276 124 276 124 400 276 400 276 276 400 276 400 124 276 124"></polygon>
</svg>
you can target your svg icon the same as the background, but you need to use "fill" instead of "background-color"
try replacing with this:
$(document).ready(function() {
$(".cls-1").css("fill",randomColor())
$('#Layer_1').click(function() {
$('body').each(function() {
$(this).css('background',randomColor());
$(".cls-1").css("fill",randomColor())
});
});
});
The smallest code!Enjoy it!
function changecolor() {
var colors = ["red", "blue", "yellow"];
Shuffle(colors);
document.body.style.backgroundColor = colors[0];
}
function Shuffle(o) {
for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
};
<body onload="changecolor()">
<h1>Hello World!</h1>
</body>
I found some interesting code on petercollingridge.co.uk for dragging SVGs.
After a while of trying to get it to work in my project, I decided to just try to get Peter's code to run in a fiddle.
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" width="400" height="200">
<style>
.draggable {
cursor: move;
}
</style>
<script type="text/ecmascript">
< ![CDATA[
var selectedElement = 0;
var currentX = 0;
var currentY = 0;
var currentMatrix = 0;
function selectElement(evt) {
selectedElement = evt.target;
currentX = evt.clientX;
currentY = evt.clientY;
currentMatrix = selectedElement.getAttributeNS(null, "transform").slice(7, -1).split(' ');
for (var i = 0; i < currentMatrix.length; i++) {
currentMatrix[i] = parseFloat(currentMatrix[i]);
}
selectedElement.setAttributeNS(null, "onmousemove", "moveElement(evt)");
selectedElement.setAttributeNS(null, "onmouseout", "deselectElement(evt)");
selectedElement.setAttributeNS(null, "onmouseup", "deselectElement(evt)");
}
function moveElement(evt) {
var dx = evt.clientX - currentX;
var dy = evt.clientY - currentY;
currentMatrix[4] += dx;
currentMatrix[5] += dy;
selectedElement.setAttributeNS(null, "transform", "matrix(" + currentMatrix.join(' ') + ")");
currentX = evt.clientX;
currentY = evt.clientY;
}
function deselectElement(evt) {
if (selectedElement != 0) {
selectedElement.removeAttributeNS(null, "onmousemove");
selectedElement.removeAttributeNS(null, "onmouseout");
selectedElement.removeAttributeNS(null, "onmouseup");
selectedElement = 0;
}
}
]] >
</script>
<rect x="0.5" y="0.5" width="399" height="199" fill="none" stroke="black" />
<rect class="draggable" x="30" y="30" width="80" height="80" fill="blue" transform="matrix(1 0 0 1 25 20)" onmousedown="selectElement(evt)" />
<rect class="draggable" x="160" y="50" width="50" height="50" fill="green" transform="matrix(1 0 0 1 103 -25)" onmousedown="selectElement(evt)" />
</svg>
I'm still getting the errors I was in my project, those being:
" Uncaught SyntaxError: Unexpected token <" and "Uncaught ReferenceError: selectElement is not defined "
I read something about invisible characters causing the first problem if you copy/paste code, but I haven't found any.
Thanks for any help you can offer.
Like others said, just remove the CDATA jumbo. Here is an updated fiddle:
https://jsfiddle.net/88pocqsr/1/
We've removed < ![CDATA[ and ]]>
Change the line
< ![CDATA[
to
<![CDATA[
(remove space between < and !)
and the line
]] >
to
]]>