SVG connect two points with a line - svg

Is there any way to connect two point using a line in SVG .I am having the following to create point in SVG.
<?xml version="1.0" standalone="no"?>
<svg width="200px" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M10 10"/>
<!-- Points -->
<circle cx="10" cy="10" r="2" fill="red"/>
<circle cx="90" cy="90" r="2" fill="red"/>
<circle cx="90" cy="10" r="2" fill="red"/>
<circle cx="10" cy="90" r="2" fill="red"/>
</svg>
I need to draw a line between points using jquery functions.

You can use a line:
<line x1="10" y1="10" x2="90" y2="90" stroke-width="1" stroke="black"/>
Or a path:
<path d="M10 10 90 90" stroke-width="1" stroke="black"/>
Why do you need jQuery?

If you want to allow the user to connect the dots you need to dynamically change the points of the line or path. There are a few ways to do this however it can be done by tracking the start point then updating the line on mouse move.
var line = $("line");
var svg = $("svg");
var isDown = false;
var startX = 0;
var startY = 0;
$("circle").on("mousedown", function(event){
isDown = true;
var pOffset = svg.offset();
startX = event.clientX - pOffset.left,
startY = event.clientY - pOffset.top;
})
$("circle").on("mouseup", function(){
isDown = false;
})
svg.on("mousemove", function(event){
if(isDown){
var pOffset = svg.offset(),
px = event.clientX - pOffset.left,
py = event.clientY - pOffset.top;
line.attr("x1",startX)
line.attr("x2",px)
line.attr("y1",startY)
line.attr("y2",py)
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<svg width="200px" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<circle cx="10" cy="10" r="10" fill="red"/>
<circle cx="90" cy="90" r="10" fill="red"/>
<circle cx="90" cy="10" r="10" fill="red"/>
<circle cx="10" cy="90" r="10" fill="red"/>
<line id="line" x1="10" y1="10" x2="90" y2="90" stroke="red" />
</svg>

Related

Height and width attribute of embedded SVG is not being reflected in the browser

When I try to embed an svg within another svg, the height and width of the embedded svg is not respected by the browser and it just defaults to the size of the painted element inside of the svg. This is a problem as I wish to show the effect of a change to the view box attribute on the embedded svg and will hence need some space around the actual element painted into the svg. Is there a way to force the browser to respect the embedded svg's height and width attributes
Example code
<div id='main'>
<svg id="svg-container" width="1200" height="600" >
<defs>
<marker id="1" refX="5" refY="5" markerUnits="markerWidth" markerWidth="10" markerHeight="10">
<circle cx="5" cy="5" r="2" fill="rgb(255,0,0)"></circle>
</marker>
</defs>
<line x1="0" y1="200" x2="100%" y2="200" stroke='white' stroke-width="2" stroke-dasharray='5,5'/>
<line x1="0" y1="400" x2="100%" y2="400" stroke='white' stroke-width="2" stroke-dasharray='5,5'/>
<line x1="200" y1="0" x2="200" y2="100%" stroke='white' stroke-width="2" stroke-dasharray='5,5'/>
<line x1="400" y1="0" x2="400" y2="100%" stroke='white' stroke-width="2" stroke-dasharray='5,5'/>
<line x1="600" y1="0" x2="600" y2="100%" stroke='white' stroke-width="2" stroke-dasharray='5,5'/>
<line x1="800" y1="0" x2="800" y2="100%" stroke='white' stroke-width="2" stroke-dasharray='5,5'/>
<line x1="1000" y1="0" x2="1000" y2="100%" stroke='white' stroke-width="2" stroke-dasharray='5,5'/>
<svg x='0' y="0" id="svg-1" width="200" height="200">
<circle cx="100" cy="100" r="50" fill="red" stroke="yellow" stroke-width="5" ></circle>
</svg>
<svg x='200' y="0" id="svg-2" width="200" height="200">
<rect x="50" y="50" width="100" height="100" fill="blue" stroke="#27f902" stroke-width="2" ></circle>
</svg>
<svg x='400' y="0" id="svg-2" width="200" height="200">
<rect x="50" y="50" rx="50" ry="20" width="100" height="100" fill="rgb(201, 52, 235)" stroke="blue" stroke-width="2" ></circle>
</svg>
</svg>
</div>

How to exclude shapes in svg or canvas?

Forgive my English
I am using svg with filters, but faced the following problem.
This is the base for svg. The result is expected:
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
<g>
<circle id="2" cx="50" cy="50" r="50"/>
<g id="1">
<rect x="0" y="0" width="50" height="50" fill="#ccc"/>
<rect x="50" y="50" width="50" height="50" fill="#ccc"/>
</g>
</g>
</svg>
But with the filter feComposite:
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
<defs>
<filter id="myFilter1">
<feImage href="#1" result="1"/>
<feImage href="#2" result="2"/>
<feComposite in="1" in2="2" operator="xor"/>
</filter>
</defs>
<g filter="url(#myFilter1)">
<circle id="2" cx="50" cy="50" r="50"/>
<g id="1">
<rect x="0" y="0" width="50" height="50" fill="#ccc"/>
<rect x="50" y="50" width="50" height="50" fill="#ccc"/>
</g>
</g>
</svg>
As you can see, the image is shifted. If you inspect the code, the blocks will not match the visible image:
Here with the addition of interactivity:
const value = (max = 100000000, min = 0) => Math.round(Math.random() * (max - min)) + min;
const createCircle = (size) => {
const r = value(10, 3);
const cx = value(size - r - 10, r + 10);
const cy = value(size - r - 10, r + 10);
return {
r,
cx,
cy
}
};
const createCircles = (counts, size) => Array(counts).fill().map(() => createCircle(size));
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
position: {
x: 0,
y: 0,
}
};
this.size = 300;
this.circlesData = createCircles(100, this.size);
const getCoords = (c, i) => c + (this.state.position.x * 0.002 * c * (i % 2 ? 1 : -1));
this.circles = () => this.circlesData.map((item, i) => <circle key = {`circles_12dew1_${i}`} cx={getCoords(item.cx, i)} cy={getCoords(item.cy, i)} r={item.r}/>);
}
onMouseMove = e => {
const position = {
x: e.pageX,
y: e.pageY,
};
this.setState({position});
}
render() {
return (
<div className = "App" >
<svg onMouseMove={this.onMouseMove} ref = {elem => this.svg = elem} xmlns = "http://www.w3.org/2000/svg" width = {this.size} height = {this.size} viewBox={`0 0 ${this.size} ${this.size}`}>
<defs>
<filter id="myFilter1">
<feImage href="#1" result="1"/>
<feImage href="#2" result="2"/>
<feComposite in ="1" in2="2" operator="xor"/>
</filter>
</defs>
<g id = "3" filter = "url(#myFilter1)" >
<circle id = "2" cx={this.size / 2 + 100} cy={this.size / 2 + 100} r={this.size / 3}/>
<g id="1"> {this.circles()} </g>
</g>
</svg>
</div>
);
}
}
ReactDOM.render( < App / > , document.getElementById('root'));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
As you can see, a big circle is moving, but it shouldn't be doing that.
How to fix?
Or how to make the exception of figures as in the interactive example without svg? For example using canvas, thank you!
The image placement behaviour you are seeing is because <feImage> elements are positioned using the filter region, or filter primitive region.
https://www.w3.org/TR/SVG11/single-page.html#filters-feImageElement
By default the filter region is an area that is 10% bigger than the original object on all sides.
x="-10%" y="-10%" width="120%" height="120%"
This is done to cater for filter primitives, such as <feGuassianBlur>, which extend outside the original size and would otherwise get clipped.
To get the images to position how you want, change the filter region, or filter primitive region, to be the same size as the original object. For example:
<feImage href="#1" x="0" y="0" width="100%" height="100%" result="1"/>
Updated demo:
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
<defs>
<filter id="myFilter1">
<feImage href="#1" x="0" y="0" width="100%" height="100%" result="1"/>
<feImage href="#2" x="0" y="0" width="100%" height="100%" result="2"/>
<feComposite in="1" in2="2" operator="xor"/>
</filter>
</defs>
<g filter="url(#myFilter1)">
<circle id="2" cx="50" cy="50" r="50"/>
<g id="1">
<rect x="0" y="0" width="50" height="50" fill="#ccc"/>
<rect x="50" y="50" width="50" height="50" fill="#ccc"/>
</g>
</g>
</svg>

Fill a path node in Draw2d touch

Im trying to make an arrow joining a rect and a path (triangle). This is my code:
var svgCarga = [
'<svg xmlns="http://www.w3.org/2000/svg" version="1.1">',
'<rect opacity="0" height="50" width="50" y="0" x="0" stroke-width="0" stroke="#000" fill="#fff"/>',
'<rect stroke="#000" height="29.875" width="4" y="6.3125" x="23" stroke-width="0" fill="#000000"/>',
'<path fill="#000000" stroke="#000" d="m17.41375,36.090939l7.4375,10l7.4375,-10l-14.875,0z" stroke-width="1"/>',
'</svg>',
].join();
Carga = draw2d.SVGFigure.extend({
NAME: 'Carga',
init: function() {
this._super();
this.width = 65;
this.height = 65;
},
getSVG: function() {
return svgCarga;
}
});
As you can see, the path has an attribute: fill="#000000" but when is rendered shows fill="none"... if i change this attribute manually, shows the path filled.
i don't know what do you want to do exactly.
I think you can't fill an SVG Path in Draw2D for now (keep in mind that the SVGFigure import is currently very limited)
'<path fill="#000000" stroke="#000" d="m17.41375,36.090939l7.4375,10l7.4375,-10l-14.875,0z" stroke-width="1"/>'
You can use polygon to do that, like this:
'<polygon points="25,45 15,35 35,35" fill="#000000" stroke="#000" stroke-width="1" />'
Hope it's what you want :)
Reference:
http://draw2d.org/draw2d_touch/jsdoc_5/#!/guide/extending_svg_figure

Pausing AnimateMotion on mouseover

I have the following SVG code.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="500" preserveAspectRatio="none">
<svg x="10">
<g>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#A2B2B1" d="M78.447-0.167c46.51-0.516,69.627,42,81.004,77.004
c12.313,37.886-7.802,73.92-35.002,82.504C82.63,172.54,33.583,136.621,14.944,115.339c-7.92-9.042-19.932-22.157-14.001-41.502
c9.402-30.666,31.449-50.303,56.003-66.003C64.113,5.167,71.281,2.5,78.447-0.167z"
onmouseover="this.style.stroke = '#000000'; this.style['stroke-width'] = 1;"
onmouseout="this.style.stroke = '#000000'; this.style['stroke-width'] = 0;"/>
<animateMotion
path="M14.088,6.647c5.426,0,13.935,0.083,16.278,4.281
c2.343,4.199,8.151,8.273,2.726,12.678c-5.426,4.405-2.753-6.984-10.337-8.479c-7.584-1.496-5.103,5.973-10.528,5.973
S0.557,10.939,6.293,6.647C10.917,3.188,8.663,6.647,14.088,6.647z"
begin="0s" dur="5s" repeatCount="indefinite"
/>
</g>
</svg>
<svg x="200">
<g>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#D8D3DE" d="M78.447-0.167c46.51-0.516,69.627,42,81.004,77.004
c12.313,37.886-7.802,73.92-35.002,82.504C82.63,172.54,33.583,136.621,14.944,115.339c-7.92-9.042-19.932-22.157-14.001-41.502
c9.402-30.666,31.449-50.303,56.003-66.003C64.113,5.167,71.281,2.5,78.447-0.167z"
onmouseover="this.style.stroke = '#000000'; this.style['stroke-width'] = 1;"
onmouseout="this.style.stroke = '#000000'; this.style['stroke-width'] = 0;"/>
<animateMotion
path="M38.69,22.497c-7.039,3.198-18.123,8.114-23.417,4.53
C9.979,23.443,0.254,22.048,4.927,13.642c4.673-8.406,7.322,6.636,17.965,3.935S26.304,7.508,33.343,4.311
s20.598,5.138,15.461,13.592C44.664,24.718,45.729,19.3,38.69,22.497z"
begin="0s" dur="5s" repeatCount="indefinite"
/>
</g>
</svg>
</svg>
is it possible to pause the animateMotion on mouse over and then restart it on mouse out.
Hosted here if you wanted to see it working - http://cdpn.io/cIfCv
It's possible to pause and unpause all declarative animations in an svg, like this:
<svg id="root" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="500" preserveAspectRatio="none">
<svg x="10">
<g>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#A2B2B1" d="M78.447-0.167c46.51-0.516,69.627,42,81.004,77.004
c12.313,37.886-7.802,73.92-35.002,82.504C82.63,172.54,33.583,136.621,14.944,115.339c-7.92-9.042-19.932-22.157-14.001-41.502
c9.402-30.666,31.449-50.303,56.003-66.003C64.113,5.167,71.281,2.5,78.447-0.167z" stroke-width="1" stroke="none" onmouseover="pause(); this.style.stroke='#000000';" onmouseout="unpause(); this.style.stroke='none';" />
<animateMotion path="M14.088,6.647c5.426,0,13.935,0.083,16.278,4.281
c2.343,4.199,8.151,8.273,2.726,12.678c-5.426,4.405-2.753-6.984-10.337-8.479c-7.584-1.496-5.103,5.973-10.528,5.973
S0.557,10.939,6.293,6.647C10.917,3.188,8.663,6.647,14.088,6.647z" begin="0s" dur="5s" repeatCount="indefinite" />
</g>
</svg>
<svg x="200">
<g>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#D8D3DE" d="M78.447-0.167c46.51-0.516,69.627,42,81.004,77.004
c12.313,37.886-7.802,73.92-35.002,82.504C82.63,172.54,33.583,136.621,14.944,115.339c-7.92-9.042-19.932-22.157-14.001-41.502
c9.402-30.666,31.449-50.303,56.003-66.003C64.113,5.167,71.281,2.5,78.447-0.167z" stroke-width="1" onmouseover="pause(); this.style.stroke = '#000000';" onmouseout="unpause(); this.style.stroke = 'none';" />
<animateMotion path="M38.69,22.497c-7.039,3.198-18.123,8.114-23.417,4.53
C9.979,23.443,0.254,22.048,4.927,13.642c4.673-8.406,7.322,6.636,17.965,3.935S26.304,7.508,33.343,4.311
s20.598,5.138,15.461,13.592C44.664,24.718,45.729,19.3,38.69,22.497z" begin="0s" dur="5s" repeatCount="indefinite" />
</g>
</svg>
<script>
var svg = document.getElementById("root");
function pause() {
svg.pauseAnimations();
}
function unpause() {
svg.unpauseAnimations();
}
</script>
</svg>
See fiddle.

Rotate SVG group indefinitely 360 degrees without CSS or Java

This is my first time diving into SVG. Is it possible to rotate this group 360 indefinitely without css or javascript/jquery? So far I have it rotating in the top left corner but I cannot seem to figure out how to center it.
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="576" height="576" viewBox="0 0 288 288" xmlns="http://www.w3.org/2000/svg" version="1.1">
<g id="seed" transform="translate(144,144)" stroke-width="2" stroke="black" fill="none" >
<circle cx="0" r="64" />
<circle cx="64" r="64" />
<circle cx="64" r="64" transform="rotate(60)" />
<circle cx="64" r="64" transform="rotate(120)" />
<circle cx="64" r="64" transform="rotate(180)" />
<circle cx="64" r="64" transform="rotate(240)" />
<circle cx="64" r="64" transform="rotate(300)" />
<circle cx="0" r="128" />
<animateTransform attributeType="xml" attributeName="transform" type="rotate" values="0 0 0; 360 0 0" dur="5s" repeatCount="indefinite" />
</g>
</svg>
Your animateTransform overwrites the transform on the <g> element. Looks like you want to provide an additional transform which you would with the attribute additive="sum"
<svg width="576" height="576" viewBox="0 0 288 288" xmlns="http://www.w3.org/2000/svg" version="1.1">
<g id="seed" transform="translate(144,144)" stroke-width="2" stroke="black" fill="none" >
<circle cx="0" r="64" />
<circle cx="64" r="64" />
<circle cx="64" r="64" transform="rotate(60)" />
<circle cx="64" r="64" transform="rotate(120)" />
<circle cx="64" r="64" transform="rotate(180)" />
<circle cx="64" r="64" transform="rotate(240)" />
<circle cx="64" r="64" transform="rotate(300)" />
<circle cx="0" r="128" />
<animateTransform attributeType="xml" attributeName="transform" type="rotate" values="0 0 0; 360 0 0" dur="5s" additive="sum" repeatCount="indefinite" />
</g>
</svg>
PaEDIT: My bad you probally mean JavaScript.
Okay you can calculate the center with JavaScript and a nice SVG-method called getBBox();
A method to return center of SVG-elements so your should also be possible. Okay piece of code
var svg = {
getCenterPosition: function(elem) {
// use the native SVG interface to get it's boundingBox
var bbox = elem.getBBox();
// return the center of the bounding box
return {
px: (bbox.x + bbox.width / 2).toFixed(2),
py: (bbox.y + bbox.height / 2).toFixed(2)
};
}
}
svg.getCenterPosition(yourGElementAsParameter); will return the center-coordinates. (web developer console or Firebug or something) Then you can set these coordinates in your attributes but don't alter the viewbox or anything it will now rotate around it's center.

Resources