Onclick JavaScript Variables - javascript

Java script -
I am trying to do this task to get into coding but it's getting a bit confusing
My HTML:
<svg height="400" width="400">
<circle cx="205" cy="203" r="150" fill="black" />
<circle cx="200" cy="200" r="150" fill="#FFCE54"/>
<circle cx="150" cy="160" r="43" fill="black" />
<circle cx="150" cy="160" r="40" fill="white" />
<circle cx="250" cy="160" r="43" fill="black" />
<circle cx="250" cy="160" r="40" fill="white" />
<circle cx="150" cy="160" r="20" fill="black"/>
<circle cx="250" cy="160" r="20" fill="black"/>
<circle cx="145" cy="154" r="5" fill="white"/>
<circle cx="245" cy="154" r="5" fill="white"/>
<path d="M 135.5,260 q 65,45 130,0"
stroke="red" stroke-width="12" fill-opacity="0" />
id="mouth"/>
</svg>
My Javascript code:
faceShape.onclick = function(){
faceShape.setAttribute("fill", "#A0D468");
};
The problem is that when I run the code, I get this error -> Uncaught TypeError: Cannot set property 'onclick' of null"
Please help. Am I doing something wrong?

faceShape does not appear anywhere in your markup. I am guessing based on what you provided that you want to add an id="faceShape" to your <circle> elements or something similar. The error message is saying that there is nothing assigned to faceShape that is why it can't read any property of null.
<svg height="400" width="400">
<circle cx="205" cy="203" r="150" fill="black" />
<circle id="faceShape" cx="200" cy="200" r="150" fill="#FFCE54"/> //added id
<circle cx="150" cy="160" r="43" fill="black" />
<circle cx="150" cy="160" r="40" fill="white" />
<circle cx="250" cy="160" r="43" fill="black" />
<circle cx="250" cy="160" r="40" fill="white" />
<circle cx="150" cy="160" r="20" fill="black"/>
<circle cx="250" cy="160" r="20" fill="black"/>
<circle cx="145" cy="154" r="5" fill="white"/>
<circle cx="245" cy="154" r="5" fill="white"/>
<path d="M 135.5,260 q 65,45 130,0"
stroke="red" stroke-width="12" fill-opacity="0" />
id="mouth"/>
</svg>
I fully changed your javascript to make the click work:
document.getElementById("faceShape").addEventListener("click", change);
function change() {
document.getElementById("faceShape").setAttribute("fill", "#A0D468")
};
Here is a working jsfiddle of what I think you're trying to accomplish: https://jsfiddle.net/g0k5joxq/1/
If not then you can use the code to extrapolate to your circumstances.

Related

Click and drag to select and move points on a SVG

With a SVG with lines and points like this:
svg line { stroke: black; stroke-width: 2px; }
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" id="svg">
<circle id="1a" cx="20" cy="20" r="3"></circle><circle id="1b" cx="20" cy="120" r="3"></circle><line id="1c" x1="20" y1="20" x2="20" y2="120"></line>
<circle id="2a" cx="20" cy="120" r="3"></circle><circle id="2b" cx="60" cy="80" r="3"></circle><line id="2c" x1="20" y1="120" x2="60" y2="80"></line>
<circle id="3a" cx="60" cy="80" r="3"></circle><circle id="3b" cx="100" cy="120" r="3"></circle><line id="3c" x1="60" y1="80" x2="100" y2="120"></line>
<circle id="4a" cx="100" cy="120" r="3"></circle><circle id="4b" cx="140" cy="100" r="3"></circle><line id="4c" x1="100" y1="120" x2="140" y2="100"></line>
<circle id="5a" cx="140" cy="100" r="3"></circle><circle id="5b" cx="100" cy="20" r="3"></circle><line id="5c" x1="140" y1="100" x2="100" y2="20"></line>
</svg>
is there a way with a HTML <svg> to be able to click and drag to select points? So that we can then mouse drag to move these points?
Before re-inventing the wheel, are there ways to do this directly with a <svg>?
For example, how to use the Drag and Drop API (see https://coursesweb.net/javascript/drag-drop-html5-attributes_t) to achieve this:
<tag draggable='true' ondragstart='handler(event)' id='draggable_elm'>Content</tag>
for SVG elements?

JavaScript SVG Zoom moves the SVG

I've written this code for my SVG, when the user scrolls, the svg zooms in/zooms out.
svgRootNode.addEventListener('wheel', function (e) {
let transformationMatrix = this.getAttribute("transform").replace("matrix(", "").replace(")", "").trim().split(" ");
let deltaZoom = e.wheelDelta / 1800;
transformationMatrix[0] = Number(transformationMatrix[0]) + deltaZoom;
transformationMatrix[3] = Number(transformationMatrix[3]) + deltaZoom;
if (transformationMatrix[0] <= 0) {
transformationMatrix[0] = 0.05;
}
if (transformationMatrix[3] <= 0) {
transformationMatrix[3] = 0.05;
}
this.setAttribute("transform", "matrix(" + transformationMatrix.join(" ") + ")");
});
Here's my SVG Markup:
<svg width="2500" height="240" transform="matrix(1 0 0 1 0 0)">
<rect data-id="1" x="20" y="20" width="100" height="100" fill="#03A9F4"></rect>
<circle cx="30" cy="130" r="4" fill="red"></circle>
<circle cx="10" cy="50" r="4" fill="red"></circle>
<text x="70" y="70" fill="rgb(255, 255, 255)" font-family="Verdana" font-size="12" text-anchor="middle" dominant-baseline="middle">Meeting Room</text>
<rect data-id="2" x="140" y="20" width="200" height="100" fill="#8BC34A"></rect>
<circle cx="130" cy="40" r="4" fill="red"></circle>
<text x="240" y="70" fill="rgb(255, 255, 255)" font-family="Verdana" font-size="12" text-anchor="middle" dominant-baseline="middle">Pantry</text>
<rect data-id="3" x="0" y="140" width="500" height="100" fill="#795548"></rect>
<circle cx="250" cy="130" r="4" fill="red"></circle>
<text x="250" y="190" fill="rgb(255, 255, 255)" font-family="Verdana" font-size="12" text-anchor="middle" dominant-baseline="middle">Workspace</text>
<rect data-id="4" x="500" y="140" width="2000" height="100" fill="#000000"></rect>
<circle cx="750" cy="130" r="4" fill="red"></circle>
<text x="1500" y="190" fill="rgb(255, 255, 255)" font-family="Verdana" font-size="12" text-anchor="middle" dominant-baseline="middle">Workspace 2</text>
<circle cx="10" cy="130" r="2" fill="black"></circle>
<circle cx="130" cy="130" r="2" fill="black"></circle>
<circle cx="340" cy="130" r="2" fill="black"></circle>
<circle cx="130" cy="10" r="2" fill="black"></circle>
<circle cx="30" cy="130" r="2" fill="black"></circle>
<circle cx="130" cy="40" r="2" fill="black"></circle>
<circle cx="250" cy="130" r="2" fill="black"></circle>
<circle cx="10" cy="10" r="2" fill="black"></circle>
<circle cx="10" cy="50" r="2" fill="black"></circle>
<line x1="30" y1="120" x2="30" y2="130" stroke="green"></line>
<line x1="30" y1="130" x2="130" y2="130" stroke="green"></line>
<line x1="130" y1="130" x2="130" y2="40" stroke="green"></line>
<line x1="130" y1="40" x2="140" y2="40" stroke="green"></line>
</svg>
Before I scroll, it looks like this:
After I zoom-out using scroll, it becomes this way. It leaves a while gap. How do I prevent that gap?

SVG loader won't animate properly when there's a heavy background JS load. Is this fixable?

I'm using a basic SVG loader while my site does some heavy JS work, but it hardly animates at all. Can I do something to give it priority in the browser? I'm very happy for the JS execution to be 0.01s slower if it means the SVG will animate properly.
If I remove the JS from my site the svg animates perfectly, but once the JS is running it barely animates at all. This is in Chrome 69.
This is the svg file:
<svg width="42" height="42" viewBox="0 0 42 42" xmlns="http://www.w3.org/2000/svg">
<circle cx="5" cy="5" r="5" fill-opacity=".8"><animate attributeName="fill-opacity" begin="0s" dur="2s" values=".8;.1;.8" calcMode="linear" repeatCount="indefinite"/></circle>
<circle cx="5" cy="21" r="5" fill-opacity=".2"><animate attributeName="fill-opacity" begin="0s" dur="1.8s" values=".1;.8;.1" calcMode="linear" repeatCount="indefinite"/></circle>
<circle cx="5" cy="37" r="5" fill-opacity=".4"><animate attributeName="fill-opacity" begin="0s" dur="1.6s" values=".8;.1;.8" calcMode="linear" repeatCount="indefinite"/></circle>
<circle cx="21" cy="5" r="5" fill-opacity=".8"><animate attributeName="fill-opacity" begin="0s" dur="1.4s" values=".1;.8;.1" calcMode="linear" repeatCount="indefinite"/></circle>
<circle cx="21" cy="21" r="5" fill-opacity=".4"><animate attributeName="fill-opacity" begin="0s" dur="1.2s" values=".8;.1;.8" calcMode="linear" repeatCount="indefinite"/></circle>
<circle cx="21" cy="37" r="5" fill-opacity=".2"><animate attributeName="fill-opacity" begin="0s" dur="1.4s" values=".8;.1;.8" calcMode="linear" repeatCount="indefinite"/></circle>
<circle cx="37" cy="5" r="5" fill-opacity=".4"><animate attributeName="fill-opacity" begin="0s" dur="1.6s" values=".8;.1;.8" calcMode="linear" repeatCount="indefinite"/></circle>
<circle cx="37" cy="21" r="5" fill-opacity=".6"><animate attributeName="fill-opacity" begin="0s" dur="1.8s" values=".8;.1;.8" calcMode="linear" repeatCount="indefinite"/></circle>
<circle cx="37" cy="37" r="5" fill-opacity=".8"><animate attributeName="fill-opacity" begin="0s" dur="2s" values=".1;.8;.1" calcMode="linear" repeatCount="indefinite"/></circle>
</svg>
Thanks!
I believe Web Workers is exactly what you need!
A web worker is a JavaScript running in the background, without affecting the performance of the page.
You need to extract your heavy js code into it so you can improve page performance.
Instead of using SMIL animations you may try CSS animations (better supported)
circle{
animation:changeOpacity var(--d) infinite
}
#keyframes changeOpacity{
0%{fill-opacity:var(--a)}
50%{fill-opacity:var(--b)}
100%{fill-opacity:var(--c)}
}
<svg width="42" height="42" viewBox="0 0 42 42" xmlns="http://www.w3.org/2000/svg">
<circle cx="5" cy="5" r="5" style="--a:.8;--b:.1;--:.8;--d:1.8s"></circle>
<circle cx="5" cy="21" r="5" style="--a:.1;--b:.8;--:.1;--d:1.8s"></circle>
<circle cx="5" cy="37" r="5" style="--a:.8;--b:.1;--:.8;--d:1.6s"></circle>
<circle cx="21" cy="5" r="5" style="--a:.1;--b:.8;--:.1;--d:1.4s"></circle>
<circle cx="21" cy="21" r="5" style="--a:.8;--b:.1;--:.8;--d:1.2s"></circle>
<circle cx="21" cy="37" r="5" style="--a:.8;--b:.1;--:.8;--d:1.4s"></circle>
<circle cx="37" cy="5" r="5" style="--a:.8;--b:.1;--:.8;--d:1.6s"></circle>
<circle cx="37" cy="21" r="5" style="--a:.8;--b:.1;--:.8;--d:1.8s"></circle>
<circle cx="37" cy="37" r="5" style="--a:.8;--b:.1;--:.8;--d:2s"></circle>
</svg>

Create a polygon in SVG from a group of elements in JS

I have an SVG with groups of elements (which are all a uniform shape but the group shape can vary. Obviously putting an outline on the group will give me a rectangle shape. What I am trying to achieve is a polygon that outlines the group giving a rough trace of the items:
http://codepen.io/wroughtec/pen/OXvRrq
(below is an example with circles although have also included a path example as that is what I am actually being given)
<h2>No Outline</h2>
<svg viewbox="0 0 1000 200">
<g>
<circle cx="20" cy="20" r="10" fill="grey" />
<circle cx="50" cy="20" r="10" fill="grey" />
<circle cx="50" cy="50" r="10" fill="grey" />
<circle cx="80" cy="50" r="10" fill="grey" />
<circle cx="110" cy="50" r="10" fill="grey" />
<circle cx="140" cy="50" r="10" fill="grey" />
<circle cx="50" cy="80" r="10" fill="grey" />
<circle cx="80" cy="80" r="10" fill="grey" />
<circle cx="110" cy="80" r="10" fill="grey" />
<circle cx="140" cy="80" r="10" fill="grey" />
<circle cx="170" cy="80" r="10" fill="grey" />
<circle cx="200" cy="80" r="10" fill="grey" />
<circle cx="170" cy="110" r="10" fill="grey" />
<circle cx="200" cy="110" r="10" fill="grey" />
</g>
</svg>
I need to be able to do this automatically in JS but getting the x and y of the circles gives me the center point so my manual one I have had to cheat to expand to the outer shape of the circles and remove unnecessary points (i.e. points on the same line or in the middle).
It sounds like what you're looking for is the convex hull of the points.
D3.js implements this, and a good example can be found here. (The code is rather lengthy, so I won't reproduce it here; the main function of interest is d3.geom.hull)
Note that D3.js v4 was just recently released, and almost all code online (including what I linked) is written for v3. There are significant changes between the two, but v4 still has a convex hull function.

How to move an object over a curve using javascript

I want to move an object over these curves using javascript. when i click an object the object moves on the curve.I tried animate methode of jquery plugin but it did not work.
I could not find the way to do this using javascript.Is it possible using SVG or it can be done using javascript.
please any one can guide me
With jquery path you could define several javascript animations:
https://github.com/weepy/jquery.path
you can see my code work here Demo jsFFidle
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<line class="line_svg" x1="75" y1="100" x2="275" y2="100" />
<line class="line_svg" x1="75" y1="250" x2="275" y2="250" />
<line class="line_svg" x1="75" y1="100" x2="75" y2="400" />
<line class="line_svg" x1="175" y1="100" x2="175" y2="400" />
<line class="line_svg" x1="275" y1="100" x2="275" y2="400" />
<line class="line_svg" x1="75" y1="400" x2="275" y2="400" />
<path id="path1"
d="M75,250 C 100,50 250,50 275,250"
d="M 275,250 C 250,400 100,400 75,250" fill="none" stroke="blue" stroke-width="7.06" />
<circle cx="75" cy="250" r="18" fill="blue" />
<circle cx="175" cy="100" r="18" fill="blue" />
<circle cx="275" cy="250" r="18" fill="blue" />
<circle cx="175" cy="400" r="18" fill="blue" />
<path d="M-25,-12.5 L25,-12.5 L 0,-87.5 z" fill="yellow" stroke="red" stroke-width="7.06" >
<animateTransform
attributeName="transform"
begin="0s"
dur="10s"
type="rotate"
from="0 -100 -110"
to="360 150 150"
repeatCount="1" />
<animateMotion dur="11s" repeatCount="1" rotate="auto" >
<mpath xlink:href="#path1"/>
</animateMotion>
<circle id="pointA" cx="75" cy="250" r="5" />
</svg>

Categories

Resources