two.js
A renderer agnostic two-dimensional drawing api for the web.
Two.js a two-dimensional drawing api geared towards modern web browsers. it is renderer agnostic enabling the same api to draw in multiple contexts: svg, canvas, and webgl.
I'd like to export a div to a PNG or JPG image. Basically the div has an appended a two.js object. Two.js draws with SVG which means I can't use those canvas toDataURL
alternatives I guess.
The two.js instance is a 400 by 400px box including a basic grid (horizontal & vertical lines) made using two.makeLine(x1,y1,x2,y2)
.
JavaScript should return a generated image/screenshot of that div or two.js object if possible.
Source: (StackOverflow)
In creating a two.js object, here are the parts:
var circle1 = two.makeCircle(676,326,25);
circle1.noStroke().fill = getRandomColor();
circle1.domElement = document.querySelector('#two-' + circle1.id);
$(circle1.domElement)
.css('cursor', 'pointer')
.click(function(e) {
circle1.fill = getNonMainRandomColor(getRandomColor());
});
I tried to save all the necessary parameters in an array as such:
[x position, y position, radius, color]
So I have the function
function showCircles(array) {
for(var i = 0; i < array.length; i++) {
var rotato = two.makeCircle(array[i][0],array[i][1],array[i][2]);
rotato.noStroke().fill = array[i][3];
rotato.domElement = document.querySelector('#two-' + rotato.id);
$(rotato.domElement).css('cursor', 'pointer').click(function(e) {rotato.fill = getNonMainRandomColor(getRandomColor());});
}
}
The problem with the latter is that the lines
rotato.domElement = document.querySelector('#two-' + rotato.id);
$(rotato.domElement).css('cursor', 'pointer').click(function(e) {rotato.fill = getNonMainRandomColor(getRandomColor());});
require a fresh variable every time it is fired thus the output is a group of circles that when clicked individually, only the last one changes color because of the setting that I have which is caused by var rotato
that should be new every circle and iteration.
How do I make the variable dynamic or is there a better solution to this mess?
Here is a codepen fork.
Source: (StackOverflow)
Two.js seems to only support a single value for a scale, not x,y components. Is it possible to just stretch something horizontally?
Source: (StackOverflow)
I am new to two.js. I am trying some basic experiments with rubber ball example to reposition ball on every second as per random input instead of mouse movement.
So, I have written below code, but it is removing rubber ball effect after some iteration. I don't know what is going wrong.
Second problem, after some iteration, rubber ball is changing its shape from circle to oval kind of shape.
JSFiddle: http://jsfiddle.net/2v93n/ Tried many times, but not working live with jsFiddle.
<body>
<script>
var two = new Two({
fullscreen: true,
autostart: true
}).appendTo(document.body);
Two.Resoultion = 32;
var delta = new Two.Vector();
var mouse = new Two.Vector();
var drag = 0.1;
var radius = 25;
var shadow = two.makeCircle(two.width / 2, two.height / 2, radius);
var ball = two.makeCircle(two.width / 2, two.height / 2, radius);
ball.noStroke().fill = 'green';shadow.noStroke().fill = 'rgba(0, 0, 0, 0.2)'; shadow.scale = 0.85;
function moveRubberBall() {
shadow.offset = new Two.Vector(- radius / 2, radius * 2);
_.each(ball.vertices, function(v) {
v.origin = new Two.Vector().copy(v);
});
mouse.x = Math.floor((Math.random() * 1000) + 1);
mouse.y = Math.floor((Math.random() * 600) + 1);
shadow.offset.x = 5 * radius * (mouse.x - two.width / 2) / two.width;
shadow.offset.y = 5 * radius * (mouse.y - two.height / 2) / two.height;
two.bind('update', function() {
delta.copy(mouse).subSelf(ball.translation);
_.each(ball.vertices, function(v, i) {
var dist = v.origin.distanceTo(delta);
var pct = dist / radius;
var x = delta.x * pct;
var y = delta.y * pct;
var destx = v.origin.x - x;
var desty = v.origin.y - y;
v.x += (destx - v.x) * drag;
v.y += (desty - v.y) * drag;
shadow.vertices[i].copy(v);
});
ball.translation.addSelf(delta);
shadow.translation.copy(ball.translation);
shadow.translation.addSelf(shadow.offset);
});
}
var auto_refresh = setInterval("moveRubberBall()", 1000);
</script>
</body>
Please help somebody.
Source: (StackOverflow)
I am using Two.JS to render shapes to the stage which have been interpreted from an SVG using the Two.js interpret method.
These have an lifespan property added, and in Two's render loop I check for the illustration and remove it if the time is up.
This is working most of the time (>99%), but occasionally the shape gets stuck and I get this error:
Uncaught NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
showIllustration: (which) =>
alreadyIllustration = false
for shape, i in @_shapes
if shape.isIllustration is true
alreadyIllustration = true
if alreadyIllustration is false
switch which
when 'food'
if Math.random() > 0.49
id = 'currywurst'
else
id = 'pretzel'
when 'mascot'
if Math.random() > 0.49
id = 'ample'
else
id = 'bear'
when 'landmark'
if Math.random() > 0.49
id = 'tower'
else
id = 'tor'
illustration = @_two.interpret document.getElementById id
illustration.center().translation.set @_two.width / 2, @_two.height / 2
@_foreGround.add illustration
illustration.lifeSpan = 100
illustration.creationTime = new Date().getTime()
illustration.isIllustration = true
@_shapes.push illustration
and here is my loop to remove the illustrations:
removeShapes: () =>
time = new Date().getTime()
for shape, i in @_shapes by -1
if shape.lifeSpan
if time - shape.creationTime >= shape.lifeSpan
shape.remove()
@_shapes.splice i, 1
here is the relevant code from two.js where the error is occurring.
removeChild: function(id) {
var elem = this.domElement.querySelector('#' + id);
if (elem) {
this.elem.removeChild(elem);
}
},
this only happens on interpreted svg's, not with shapes. both shapes and interpreted shapes return two.polygon objects so this seems odd.
One thing I can think of is that two.js uses the id of the element it interprets as the id of the polygon made, and if there are two elements with the same id then this causes an error when trying to remove. But the alreadyIllustration check seems to work correctly every time to stop adding illustrations if there are any existing.
I also tried setting the id to the time it was created instead of the id of the element so it was unique every time, but this causes other problems and errors.
Many thanks.
Source: (StackOverflow)
I have a large circle with smaller ones inside made using two.js.
My problem is that these two do not rotate in their own place but in the top left axis.
I want the group of circles (circlesGroup
) rotate only inside the large one in a static position. The circlesGroup
and the large circle are grouped together as rotatoGroup
.
two.bind('update', function(frameCount, timeDelta) {
circlesGroup.rotation = frameCount / 120;
});
two.bind('update', function(frameCount, timeDelta) {
rotatoGroup.rotation = frameCount / 60;
});
The whole code is in CodePen.
Source: (StackOverflow)
I am trying to make a solar system model. I made it all so far using two.js. I want to make it so when the mouse is over a planet's orbit path, it'll highlight that planet's orbit, and be a link to information about that planet. I'm having trouble finding a way to do this, though.
If you don't have it, here's Two.js.
My file structure looks like this:
css
main.css
js
main.js
two.js
index.html
PS. This will not render with the "Run code snippet" feature. If you wish to see it, you must save this code and put it in the same file structure I have.
//This work was created by the minds of Sam Steele and Devin Fowler of Cryptocosm Developers.
//Cryptocosm ©2014
//cryptocosm.x10.bz
//Initiate the render context
var elem = document.getElementById('canvas');
var two = new Two({
fullscreen: true
}).appendTo(elem);
//Define our planets and their colors
var sun = two.makeCircle(0, 0, 70);
var mercury = two.makeCircle(95, 0, 7);
var venus = two.makeCircle(125, 0, 8.5);
var earth = two.makeCircle(160, 0, 11.4);
var mars = two.makeCircle(200, 0, 9.5);
var jupiter = two.makeCircle(260, 0, 28);
// For Saturn we're going to do something special in order to get the rings
var saturnBody = two.makeCircle(320, 0, 24);
var saturnRings = two.makeCurve(296, 0, 290, 10, 322, 10, 350, -8, 342, -10, true);
saturnRings.rotation = 4.5;
var saturn = two.makeGroup(saturnBody, saturnRings);
var uranus = two.makeCircle(460, 0, 18);
var neptune = two.makeCircle(540, 0, 16);
var asteroid = two.makeCircle(0, 320, 3);
//Try to make some stars
var width = window.innerWidth;
var height = window.innerHeight;
var star;
for (i = 0; i < 200; i++) {
var randX = Math.round(Math.random() * width);
var randY = Math.round(Math.random() * height);
star = two.makeCircle(randX, randY, 2);
}
//Set the color of the planets
sun.fill = '#F7CA18';
mercury.fill = '#9E9E9E';
venus.fill = '#795548';
earth.fill = '#2196F3';
mars.fill = '#FF7043';
jupiter.fill = '#E67E22';
saturnBody.fill = '#A1887F';
saturnRings.stroke = "#F5F5F5";
saturnRings.linewidth = 7;
saturnRings.noFill();
saturn.translation.set(20, 0);
uranus.fill = '#4DB6AC';
neptune.fill = '#3F51B5';
star.fill = '#FAFAFA';
asteroid.fill = '#FAFAFA';
//Group the planets
var Mercury = two.makeGroup(mercury);
var Venus = two.makeGroup(venus);
var Earth = two.makeGroup(earth);
var Mars = two.makeGroup(mars);
var Jupiter = two.makeGroup(jupiter);
var Saturn = two.makeGroup(saturn);
var Uranus = two.makeGroup(uranus);
var Neptune = two.makeGroup(neptune);
var planets = two.makeGroup(sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune);
//Center everything in the center of the element
planets.translation.set(two.width / 2, two.height / 2);
Mercury.rotation = 4;
Venus.rotation = 2.5;
Earth.rotation = 5.5;
Mars.rotation = 1;
Jupiter.rotation = 4.2;
Saturn.rotation = 2.5;
Uranus.rotation = 5.75;
Neptune.rotation = .5;
var counter = document.getElementById('counter');
var count = 0;
var yearsPassed = 0;
// Bind a function to scale and rotate the group to the animation loop.
two.bind('update', function (frameCount) {
//Set the "ZOOM" of the system
planets.scale = .8;
//Rotate all the planets
Mercury.rotation += .01607;
Venus.rotation += .01174;
Earth.rotation += .01;
/* //Earth year counter (not currently accurate at all)
count++;
if (count % 550 == 0) {
yearsPassed++;
counter.innerHTML = "An estimated " + yearsPassed + " Earth years passed";
}; */
Mars.rotation += .00802;
Jupiter.rotation += .00434;
Saturn.rotation += .00323;
Uranus.rotation += .00228;
Neptune.rotation += .00182;
//Rotate Saturn's rings so that it doesn't look dumb
saturnRings.rotation -= .00323;
}).play(); // Finally, start the animation loop
@font-face {
font-family: Roboto-Thin;
font-style: normal;
src: url(Roboto/Roboto-Thin.ttf);
}
html {
background-color: #212121;
}
body {
color: white;
font-family: Roboto-Thin;
}
#counter {
background-color: rgba(0, 0, 0, .4);
width: auto;
height: auto;
font-size: 34px;
float: left;
position: fixed;
padding: 10px;
}
#canvas {}
<html>
<head>
<title>The Solar System</title>
<link rel='nofollow' href="css/main.css" type="text/css" rel="stylesheet">
<script src="js/two.js"></script>
</head>
<body>
<div id="counter"></div>
<div id="canvas">
</div>
<script src="js/main.js"></script>
</body>
</html>
Source: (StackOverflow)
I want to draw flowers using Polar Equations on a webpage, but i want to handle each flower as an instance, possibly change them or animate them.
I was thinking of using Two.js to render and svg, but I'm not sure how to create svgs from equations.
I was also trying to use Processing.js/p5.js just as this guy did it
I'm really up for using any js library, I just want to do it efficiently and right
Source: (StackOverflow)
I wrote a simple bouncing ball animation using Two.js. It's just a ball bouncing off the walls. It works just fine for me in Chrome, but in Firefox, the ball disappears and reappears a few seconds later in another part of the screen, meaning that the ball is moving, just randomly becomes briefly invisible.
Here is my code:
var elem=document.querySelector("div");
var h=window.innerHeight;
var w=window.innerWidth;
var two=new Two({fullscreen: true}).appendTo(elem);
var vy=5, vx=5;
var circle1=two.makeCircle(300,200,50);
circle1.fill="orange";
circle1.stroke="purple";
circle1.linewidth=5;
two.bind("update", function(frameCount){
circle1.translation.x+=vx;
circle1.translation.y+=vy;
if(circle1.translation.x+30>w||circle1.translation.x-30<0){
vx*=-1;
circle1.translation.x+=vx;
}
if(circle1.translation.y+30>h||circle1.translation.y-30<0){
vy*=-1;
circle1.translation.x+=vy;
}
}).play();
JSFiddle Example
Again, the same thing works just fine in Chrome.
Also, it works fine in both Chrome and Firefox if I replace the div with a canvas and use this instead:
var canvas=document.querySelector("canvas");
var w=window.innerWidth, h=window.innerHeight;
canvas.width=w;
canvas.height=h;
var context=canvas.getContext("2d");
var vx= 5, vy=5;
var ball={
x: 300,
y: 200,
radius: 50
};
function draw(){
context.fillStyle="orange";
context.beginPath();
context.arc(ball.x,ball.y,ball.radius,0,Math.PI*2,false);
context.closePath();
context.fill();
}
(function animate(){
var timer=setInterval(function(){
context.clearRect(0,0,w,h);
ball.x+=vx;
ball.y+=vy;
if(ball.x+ball.radius>w||ball.x-ball.radius<0){
vx*=-1;
ball.x+=vx;
}
if(ball.y+ball.radius>h||ball.y-ball.radius<0){
vy*=-1;
ball.y+=vy;
}
draw();
},1000/60);
}());
If anyone can explain this strange behavior, that would be great.
Source: (StackOverflow)
I have drawn a shape using two.js and I want to write code to handle click events on that shape. Not the canvas, but on the shape itself.
front_left.domElement = $('#two-' + front_left.id)
.css('cursor', 'pointer')
.click(function(e){
alert("Hello World!");
});
This code taken from an answer that seems like it should work:
circle.domElement = $('#two-' + circle.id)
.css('cursor', 'pointer')
.click(function(e) {
circle.fill = getNonMainRandomColor(getRandomColor());
});
but it doesn't work for me using the latest JQuery and the latest two.js, and it also doesn't seem to work in the example, since the code reads as if clicking on the circles was supposed to make the colour changes but nothing happens on any browser or computer I've tried.
So, how can I capture and respond to click events of shapes/groups drawn with two.js?
Source: (StackOverflow)
I'm building a web-app using Two.js which generates shapes and then removes them again after their lifespan is up.
When making the shapes I push them into a new array which I then loop through every frame to check if the lifespan is up. If it is then the shape is removed and spliced from the array.
This works 99% of the time, but sometimes a shape does not get removed from the stage, even though it gets removed from the array. So it gets stuck and there is no reference to it so I can't remove it.
Also if I remove the 'if shape' check in the loop I get this error a lot:
Uncaught TypeError: Cannot read property 'creationTime' of undefined
which I'm sure means something is not right.
onPeak: (col) =>
circle = @_two.makeCircle @_two.width, @_two.height, @_two.height*0.75
circle.fill = col
circle.lifeSpan = Math.floor @convertToRange(@_bpm, [60,600], [1000, 400])
circle.creationTime = new Date().getTime()
circle.noStroke()
@_shapes.push circle
onTwoUpdate: () =>
if @_shapes.length >= 1
@removeShapes()
removeShapes: () =>
time = new Date().getTime()
for shape in @_shapes
if shape and time - shape.creationTime >= shape.lifeSpan
shape.remove()
@_shapes.splice shape.index, 1
Source: (StackOverflow)
If the object tag is not really suitable, then is there a more preferable method for grabbing an SVG file and manipulating it directly with two.js? Or will I have to go into the SVGs and just add them inline?
Using this question's code and some of my own edits I can't get my object to rotate, Chrome gives me the error: Uncaught TypeError: Cannot read property 'x' of undefined
HTML
<object type="image/svg+xml" data="./images/face.svg" id="face"></object>
JS
$(function(){
var svgObject = document.getElementsByTagName('object')[0];
svgObject.onload = function(){
var mySvg = svgObject.contentDocument.getElementsByTagName('svg')[0];
var two = new Two({
fullscreen:false,
autostart: true
}).appendTo(document.body);
var shape = two.interpret(mySvg);
console.log(shape);
two.update();
two.bind('update', function() {
shape.rotation += 0.01;
});
};
});
Since the code in the referenced question seems to have worked for the individual, I assume I just have a syntax error. Any ideas as to what's going on?
EDIT: With Francis' help, I was able to get my own SVG parsed for use with the for loop Francis mentioned in order to access the elements inside, but it seems to be considering the nested G tag within the following SVG to be null...for some reason:
<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="280" width="280" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/"><g id="layer1" transform="matrix(0.99999301,0,0,1,-400.71477,-954.83987)"><g id="g3836" transform="matrix(-0.08567939,-0.08567939,0.08567939,-0.08567939,574.3717,1199.1604)"><path id="path3801" fill="#3b5998" d="m805.17-1221.6c-902.43,902.43-902.43,2365.6,0.00003,3268l517.13-517.1c-616.83-616.83-616.83-1616.9,0-2233.8z"/><path id="rect3822" fill="#FFF" d="m266.93,336.2c0.15806,60.722,23.582,102.66,103.93,102.66h44.694v62.567h71.844v-62.57h184.55v-73.089h-184.55v-62.849l-71.844-8.5959v71.445h-44.69c-20.309,0-35.863-7.2042-35.863-35.676v-38.658h-64.869c-2.0284,15.729-3.2307,30.752-3.1941,44.765z"/></g></g></svg>
Also, Chrome throws the following errors on load:
'Uncaught TypeError: Cannot read property 'nodeName' of null' on line 68, in the handler() function (this is what I assumed to be the nested G being considered null):
xmlDocValue.value+=XMLdoc.childNodes.item(1).nodeName +"\n"
'Uncaught TypeError: Cannot read property 'childNodes' of undefined' in the aforementioned for loop, which I assume is because of the fact that the null element is considered null:
myGElems = XMLdoc.childNodes.item(0).childNodes
Source: (StackOverflow)
Is there any way I can interpret an external svg file with object tag in two.js?
I tried in the way below but..
HTML
<object type="image/svg+xml" data="./svg/mydrawing.svg" id="mysvg"></object>
JS
var mySvg = document.getElementById("mysvg").contentDocument;
var shape = two.interpret(mySvg);
console.log(shape);
//in console:
Uncaught TypeError: Cannot call method 'toLowerCase' of undefined
It's nice if I can import an external .svg file as my svg file is too big to write in HTML as Inline SVG.
Thanks in advance.
Source: (StackOverflow)
I have a Two.JS Polygon Object.
Now I want the x/y position of a point (the point's position is given on the curve in %)
A Two.JS Polygon has the property ending. You can give a number between 0 and 1 there.
Thats what I want for a particular point.
Is there a way to get the x/y of a point ON the curve?
Maybe it's possible with another JS Canvas/SVG Lib.
Source: (StackOverflow)