EzDevInfo.com

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.

How can I export a DIV to an Image

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)

Create dynamic Two.js variables to involve individual click event

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)

Advertisements

Is it possible to scale two.js groups in one direction

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)

Keeping shape and animation of ball consistance over period of time

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)

Two.JS : 'Failed to execute 'removeChild' on 'Node' when trying to remove shapes interpreted from SVG

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)

Weird artifacts in CocoonJS Path Demo

Im getting some weird effect while zooming out in CocoonJS's Path Demo. (Iconia A510). Thethere are missing pixels from the rectangle. If i zoom back it looks solid again (but very pixxelated). Can someone confirm that this happens on other device too?

CocoonJs Path Demo

Addendum

I guess this is related to the smae problem. The very same test code run on CocoonJS (same device) and on Win 7 / Chrome 30.0.1599.66 m

compare

Here is an another test from a Nexus 7

https://f.cloud.github.com/assets/220033/1242079/0003f2e2-2a31-11e3-8c53-282493a462a9.png

More info on TwoJS's github: https://github.com/jonobr1/two.js/issues/48


Source: (StackOverflow)

Rotate a Two.js object in its position

I have a large circle with smaller ones inside made using two.js.

greninja-aegislash-goodra

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)

How do I create circular hotspots with two.js?

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)

Creating a 2D object/image from a polar equation

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)

Bouncing ball disappearing in Firefox

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)

How to capture a click event on a shape or group in two.js?

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)

Some shapes not being removed in Two.js when looping through array of all shapes

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)

How do I properly interpret an external SVG file for use with two.js?

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)

How can I interpret an extrenal svg file in two.js

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)

Two.JS Point on Curve

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)