drawing svg element in different container using javascript - javascript

I have 2 svg container and I want to draw different svg elements in both container. Let us suppose:
<div><svg height="100" width="100" id="svg1" class="svg"> </svg></div>
<div><svg height="100" width="100" id="svg2" class="svg"> </svg></div>
Now suppose I want to draw a rectangle in 1st one and a line in 2nd one using id in javascript and snap.svg. How can i achieve it?

Read the Getting Started and Documentation part on snapsvg.io then it should be a simple task.
var s1 = Snap("#svg1");
s1.rect(50, 50, 50, 50);
var s2 = Snap("#svg2");
var line = s2.line(50, 50, 100, 100);
line.attr({
stroke: "#000",
strokeWidth: 5,
strokeLinecap:"round"
});

I just little bit enhanced the reply of #ctron with a jsfiddle and some explanations.
var s1 = Snap("#svg1")
, s2 = Snap("#svg2")
// Create rect and save in a variable
, rect = s1.rect(50, 50, 50, 50)
// Create line and save in a variable
, line = s2.line(50, 50, 100, 100);
rect.attr({fill:"red"})
line.attr({
stroke: "#0f0",
strokeWidth: 5,
strokeLinecap:"round"
});
JSFiddle

Related

Fill the intersection area between circle and function in JSXGraph

I have a circle and simple function Math.cos(x)
I want the circle to be filled when it intersects with that function (fill only the upper side). But it's not working.
Script:
// circle
var point1 = app.board.create('point', [0,0], {size: 2, strokeWidth:2 })
var point2 = app.board.create('point', [6,0], {size: 2, strokeWidth:2 })
var circle = app.board.create('circle', [point1,point2], {strokeColor: "#f00", strokeWidth: 2 })
// function
var func = app.board.create('functiongraph',[function(x){ return Math.cos(x)}]);
// intersection
var curve = app.board.create('curve', [[], []], {strokeWidth: 0, fillColor: "#09f", fillOpacity: 0.8})
curve.updateDataArray = function() {
var a = JXG.Math.Clip.intersection(circle, func, this.board);
this.dataX = a[0];
this.dataY = a[1]
};
app.board.update()
Output
Expected output (I did it on Paint)
Thank you in advance :)
This can easily realized with the next version of JSXGraph which will be released next week: With the inequality element the area above the cosine curve can be marked. The inequality element is a closed curve and can be intersected with a circle. In v1.2.3, the intersection does not work because of a small bug.
For the clipping, the next version contains new elements curveintersection, curveunion, curvedifference which make it easier to use the methods of JXG.Math.Clip, but of course your approach with JXG.Math.Clip will still work.
Here is the code:
var f = board.create('functiongraph', ['cos(x)']);
var ineq = board.create('inequality', [f], {
inverse: true, fillOpacity: 0.1
});
var circ = board.create('circle', [[0,0], 4]);
var clip = board.create('curveintersection', [ineq, circ], {
fillColor: 'yellow', fillOpacity: 0.6
});
Actually, the inequality element does the same as enxaneta does "by hand".
In the next example I'm building the d attribute for the path using Math.cos().
I suppose your function may be different.
Please observe that at the end at the d attribute the path is closing the upper part of the svg canvas.
I'm using the pth inside a clipPath and I'm clipping the circle with it.
let d ="M";
for(let x = -50; x<=50; x+=1){
d+=`${x}, ${5*Math.cos(x/5)} `
}
d+="L50,-50L-50,-50z"
pth.setAttribute("d",d);
<svg viewBox="-50 -50 100 100" width="200">
<clipPath id="clip">
<path id="pth"/>
</clipPath>
<circle r="45" clip-path="url(#clip)" fill="blue"/>
</svg>
In order to better understand how I'm building the path please take a look at the next example:
let d ="M";
for(let x = -50; x<=50; x+=1){
d+=`${x}, ${5*Math.cos(x/5)} `
}
d+="L50,-50L-50,-50z"
pth.setAttribute("d",d);
<svg viewBox="-50 -50 100 100" width="200">
<circle r="45" fill="blue"/>
<path id="pth" fill="rgba(250,0,0,.4)"/>
</svg>

Add a background image to an SVG

I am using Snap.svg and trying to add a background image to a polygon.
The polygon is as follows:
<svg id="test" height="600" width="600" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="" class=""></svg>
var polygon = s.polyline(200, 286, 250, 200, 350, 200, 400, 286, 350, 373, 250, 373);
I have tried a bunch of different ways to make the background image but none of them work:
polygon.attr(
{
fill: 'url(http://csshexagon.com/img/meow.jpg)'
});
polygon.attr('xlink:href', 'url(http://csshexagon.com/img/meow.jpg)');
Any ideas? Thanks.
There's a couple of bits you need to do. If using Snap, make sure you are using the latest version, so 'toPattern()' works.
Then we can draw the image, convert it to a pattern, and then fill the polygon with the pattern.
var polygon = paper.polyline(200, 286, 250, 200, 350, 200, 400, 286, 350, 373, 250, 373);
var img = paper.image('https://i.imgur.com/LQIsf.jpg', 150, 200, 250, 250)
var p = img.toPattern( 0,0,400,400 );
polygon.attr({ fill: p })
jsfiddle

Change Color of Shape Mid Tween

I'm trying to make an event that changes my shapes stroke color for 5 seconds when a button is clicked, and then the shape returns to original color after the duration.
I am able to do this with clearing the entire stage and redrawing new shapes (which resets their position), but I can't figure it out with the current shapes.
Q. What's the best way to approach making a change to a shapes color, during a Tween?
I was also curious if there's a better way to handling tweening the shapes width? Currently I am relying on ScaleX and ScaleY - but this also changes the stroke's size - which is not desired.
JS Fiddle
HTML
<button id="change">Click to Change Color</button>
<canvas id="demoCanvas" width="500" height="500"></canvas>
JS
var stage,
circle;
function init() {
stage = new createjs.Stage("demoCanvas");
createjs.Ticker.setFPS(60);
createjs.Ticker.addEventListener("tick", stage);
}
function createCircle(){
circle = new createjs.Shape().set({name:"circle"});
circle.graphics.setStrokeStyle(1).beginStroke("#000").beginFill( "#FFF" ).drawCircle(0, 0, 20);
circle.x = 100;
circle.y = 100;
stage.addChild(circle);
createjs.Tween.get(circle, {loop: true})
.to({x: 225, y: 225}, 1000, createjs.Ease.getPowInOut(1))
.to({x: 100, y: 100}, 1000, createjs.Ease.getPowInOut(1));
circle2 = new createjs.Shape().set({name:"circle"});
circle2.graphics.setStrokeStyle(1).beginStroke("#000").beginFill( "#FFF" ).drawCircle(0, 0, 20);
circle2.x = 400;
circle2.y = 400;
stage.addChild(circle2);
createjs.Tween.get(circle2, {loop: true})
.to({scaleX: 2, scaleY: 2, x: 425, y: 125}, 1000, createjs.Ease.getPowInOut(1))
.to({scaleX: 1, scaleY: 1, x: 400, y: 400}, 1000, createjs.Ease.getPowInOut(1));
stage.update();
}
$( "#change" ).click(function() {
// change color
});
$(document).ready(function() {
init();
createCircle();
});
There are a few questions in this post, so I will try to answer them all:
First, a solution to most of your issues is Graphic commands. Commands provide a simple way to store graphic instructions, and change them later. Here is a simple example:
var shape = new createjs.Shape();
var colorCmd = shape.graphics.beginFill("red").command;
var rectCmd = shape.graphics.drawRect(0,0,100,100).command;
// Later
colorCmd.style = "blue";
rectCmd.w = 200;
stage.update(); // Remember to update the stage after changing properties
You can read more about commands on the createjs blog. All commands and their properties are documented in the EaselJS docs.
Change a color: I outlined this in the example above, but the short answer is to adjust the style property of a fill command. If you want to change it instantly, you can just set up a Tween.call:
Example:
createjs.Tween.get(circle, {loop: true})
.to({x: 225, y: 225}, 1000, createjs.Ease.getPowInOut(1))
.call(function(tween) {
colorCmd.style = "rgba(0, 0, 255, 0.5)"; // Change to 50% blue
})
.to({x: 100, y: 100}, 1000, createjs.Ease.getPowInOut(1));
If you want to tween the color, then you could check out the ColorPlugin, which is currently in a "Plugins" branch of TweenJS: https://github.com/CreateJS/TweenJS/tree/Plugins/extras/plugins
// Tween the color from its current value to blue.
// Note that only hex, short hex, HSL, and RGB formats are supported.
createjs.Tween.get(colorCmd).to({style:"#0000ff"});
Change the size: The example above also shows how to modify the values of a drawRect call. You can do the same with any other draw command (including moveTo, lineTo, polyStar, etc).
Scaling also works, and if you want to not scale the stroke, just set the ignoreScale parameter on the stroke style.
shape.graphics.setStrokeStyle(1, null, null, null, true);

Canvas - Elements overlaying

I need to build some canvas app, but the shapes are irregular and elements are overlapping each other. I am using fabric.js for canvas and importing SVG files to draw elements, but I can't detect right hovered objects.
Here are examples:
I want to detect on mouse over when it will be above shape.
How it is actualy on my canvas (the red line corners are invisible in canvas ofc)
Example code from Fabric.js
You have to use the "perPixelTargetFind" property of fabricjs.
This will check the mouse over the object with accuracy.
If there is graphic it will trigger the target, otherwise not.
var canvas = new fabric.Canvas('canvas');
canvas.perPixelTargetFind = true;
canvas.add(new fabric.Circle({ radius: 30, fill: 'green', top: 50, left: 100 }));
canvas.add(new fabric.Circle({ radius: 30, fill: 'green', top: 100, left: 200 }));
canvas.on('mouse:over', function(e) {
e.target.setFill('red');
canvas.renderAll();
});
canvas.on('mouse:out', function(e) {
e.target.setFill('green');
canvas.renderAll();
});
<script src="http://fabricjs.com/lib/fabric.js"></script>
<canvas id='canvas' width="550" height="550" style="border:#000 1px solid;"></canvas>

Place an Image inside a Polygon with Snap.svg

I have a polygon (in fact it's a hexagon) painted with Adobe's Snap.svg:
var s = Snap('#test');
var hexagon = s.paper.polygon([
0, 50,
50, 0,
100, 0,
150, 50,
100, 100,
50, 100,
0, 50
]);
hexagon.attr({
stroke: '#fff',
strokeWidth: 1
});
Instead of filling the polygon with some paint, I want to place an image inside of it. The only thing I have found in the docs is the image function, but I don't know how to insert it. Anyone any idea?
======
Final Solution:
var image = s.paper.image('http://placekitten.com/g/200/300', 0, 0, 150, 150);
image = image.pattern(0, 0, 150, 150);
...
hexagon.attr({
stroke: '#fff',
strokeWidth: 1,
fill: image
});
You can't directly fill an element with an image you have to go via a pattern.
What this means is that you need to create a pattern that contains an image and then fill the shape with the pattern.

Categories

Resources