Morphing with Velocity.js doesnt work - javascript

Hej,
i have this plunker: http://plnkr.co/edit/bKzi6rU3lIXT4Nz2wkR8?p=info
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="stilovi/main.css">
<title>Testing</title>
</head>
<body>
<div id="avengers"></div>
</body>
<script src="snap.svg-min.js"></script>
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://rawgit.com/julianshapiro/velocity/master/velocity.min.js"></script>
<script>
function fetchXML(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onreadystatechange = function(evt) {
//Do not explicitly handle errors, those should be
//visible via console output in the browser.
if (xhr.readyState === 4) {
callback(xhr.responseXML);
}
};
xhr.send(null);
};
/*var list = ["test3.svg","test.2svg"];*/
//fetch the document
fetchXML("test3.svg", function(newSVGDoc) {
//import it into the current DOM
var n = document.importNode(newSVGDoc.documentElement, true);
document.getElementById("avengers").appendChild(n);
var ironman = document.getElementsByTagName("polygon");
var ironmanlist = Array.prototype.slice.call(ironman);
/*alert(ironmanlist.length);*/
ironmanlist.forEach(function(elem, i) {
/*for (var index = 0; index < elem.points.length; ++index){
//2.test case morphing each point (not working)//
console.log(elem.points[index]);
$.Velocity(elem.points[index],{x:100,y:100},{duration:Math.floor(Math.random() * (3000 - 1000 + 1)) + 1000}, "ease-in-out");
//3.test case morphing each point in another way (not working)//
/*$(elem.points[index])
.velocity({x:100,y:100},{duration:Math.floor(Math.random() * (3000 - 1000 + 1)) + 1000}, "ease-in-out");
console.log(elem.points[index]);
}*/
//1. working test case (translation)//
console.log(elem.points[0].x);
$.Velocity(elem, {
translateX: -300
}, {
duration: Math.floor(Math.random() * (3000 - 1000 + 1)) + 1000
}, "ease-in-out");
//$.Velocity(elem,{rotateZ:"45deg"},{duration:Math.floor(Math.random() * (3000 - 1000 + 1)) + 1000}, "ease-in-out");
console.log(elem.points[0].x);
//End of 1. working test case//
});
console.log(ironmanlist);
});
</script>
</html>
With my code, and some examples. What I want to do is morph each polygon from one SVG image, into another polygon from another SVG image. The translation works, but I'm not sure how to do a morph.
Can anyone help, or check the code and tell me what I am doing wrong?
There are a lot of polygons, and I need it to be fast so i went with velocity.js for this.
I was also thinking of maybe moving it all to three.js, and maybe convert it to a format that would be best to use with three.js. But if it is a possibilty to use it as svg and keep a great performance i would do so.

As far as I'm aware, velocity.js doesn't support this as (taken from their website):
In general, Velocity can animate any property that takes a single numeric value.
As SVG paths usually (always?) consist of multiple values, morphing is way beyond their current scope.
However, I can highly recommend Snap for morphing SVG paths.

Related

Object under cursor not found

I tried three different approaches but none worked.
I place two rectangles on the canvas and want to catch the object under the mouse cursor when a mousedown event occurred.
The stagemousedown works, but the objects are not found. Watching the debugger I see that the rectangle has still the drawrect coordinates, not the one that I set later. There is also a 'hitarea' which I don't know how to use since it is checked during hittest and getObjectUnderPoint.
Approach 1: makeButton creates a handler on lines 66ff -> it never fires
Approach 2: getObjectUnderPoint when a mousedown evt happens. -> returns always null
Approach 3: loop through each child and apply the hitttest -> returns always false.
I come from Java and C# and am far from being experienced in JS, but I had hoped that I could catch the mousedown with at least one approach.
What makes me wonder is that the x and y in the rectangle never change from the ones used during creation (0,0). That's not the current position which I set for example in 73 and 74!
I don't seem to find the REAL x and y of the object and neither does approaches 2 and 3. I wished, approach 1 would work since that makes the most sense to me.
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<link rel="stylesheet" href="./css/style.css">
<meta charset="utf-8" />
<title></title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/EaselJS/1.0.2/easeljs.js"></script>
<script>
function init() {
var followme = 0;
var canvas = document.getElementById("canvas");
var stage=new createjs.Stage(canvas);
var shape=new createjs.Shape();
var dispO = new createjs.Shape();
makeBtn(3,3);
makeBtn(300,300);
stage.on("stagemousedown", function (evt) {
followme = 1;
found=stage.getObjectUnderPoint(stage.mouseX, stage.mouseY,0)
if(found != null)
{
console.log(found);
}
var xxx=stage.children;
for (i=0; i<xxx.length;i++)
{
if (xxx[i].hitTest(stage.mouseX, stage.mouseY))
{
shape.alpha=1;
}
}
});
stage.on("stagemouseup", function (evt) {
followme = 0;
});
stage.update();
createjs.Ticker.setFPS(30);
createjs.Ticker.addEventListener("tick", handleTick);
function handleTick(event)
{
if ((followme === 1) && (dispO != null))
{
var difX = stage.mouseX - dispO.x - 100;
var difY = stage.mouseY - dispO.y - 50;
dispO.x += difX / 20;
dispO.y += difY / 20;
stage.update();
}
else
if(dispO != null)
{
var dmy=dispO;
}
}
function makeBtn(x,y)
{
shape = new createjs.Shape();
shape.graphics.beginStroke("black").setStrokeStyle(2, 0, 1).drawRect(0, 0, 200, 100);
dispO=shape;
dispO.mouseEventsEnabled = true;
var handler=dispO.on("mousedown",
function(event) {console.log(instance == this); },// true, "on" uses dispatcher scope by default.
null,
once=true,
'theButton',
useCapture=true
);
dispO.x=x;
dispO.y=y;
stage.addChild(dispO);
}
}
</script>
</head>
<body onload="init();">
<div id="outer">
<canvas id="canvas" width="500" height="600">
</canvas>
<menu id="controls">
</menu>
</div>
</body>
</html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/EaselJS/1.0.2/easeljs.js"></script>
Your demo works fine -- its just that your square has no fill, so only the border is clickable. If you add a fill, then it works great:
https://jsfiddle.net/lannymcnie/ozcr6tna/
shape.graphics.beginStroke("black")
.setStrokeStyle(2, 0, 1)
.beginFill("white") // <----- Fill call
.drawRect(0, 0, 200, 100);
If you want the clickable area to be transparent, then you can use a hitArea. Just assign a different shape with a fill as a hitArea (and don't add that shape to the stage). Hit testing in EaselJS uses pixel fill - so if there are no pixels, then there is no hit!
Hope that helps!

Separating HTML elements into columns with proper spacing (JQuery and CSS)

I am trying to make a Windows 8 like interface for my webpage. I have created articles that act as tiles and have a random generator that makes the tile small or large. I am trying to make these look like they are in columns depending on the width of the screen. When I change the screen width the tiles do not seem to be properly spaced which is driving me nuts. I am new to css and jquery so I am still learning and always open to learning new ways to do things. I would really appreciate some help on this column and spacing issue.
NOTE: My tiles usually have pictures and after I changed the code just to show up as color tiles. Now they are not always showing but I will fix that issue.
For example: each column should have a width of one double box or two single box's. And depending on the screen width...if bigger the more columns will display and the smaller the less amount of columns it will display.
Here is my current code:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="http://code.jquery.com/jquery-2.1.0.min.js" type="text/javascript"></script>
<script src="Script/jquery.lorem.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function ()
{
var colors = ["#2672ec", "#00a300", "#97009f", "#094db5", "#da532c", "#af1a3f", "#613cbc", "#008ad2"];
var doubleBoxFlag = [true, false, false, false, false, false];
var pictures = ["Images/1.jpg", "Images/2.jpg", "Images/3.jpg", "Images/4.jpg", "Images/5.jpg", "Images/6.jpg", "Images/7.jpg", "Images/8.jpg", "Images/9.jpg", "Images/10.jpg", "Images/11.jpg"];
var defaultClass = '.box';
for (var i = 0; i < Math.floor((Math.random() * 64) + 34) ; i++)
{
var rand = Math.floor(Math.random() * pictures.length);
var boxRand = Math.floor(Math.random() * doubleBoxFlag.length);
var currentClass = defaultClass + i;
var currentClassJ = 'box' + i;
//For picture tiles:
//$("#Interface").append("<article class=" + currentClassJ + " " + "style='background-image: url(" + pictures[rand] + ")" + "'><span>" + i + "</span>");
//For Color Tiles:
$("#Interface").append("<article class=" + currentClassJ + " " + "style='background-color:" + colors[rand] + "'><span>" + i + "</span>");
if (doubleBoxFlag[boxRand]) {
$(currentClass).css("width", "374px");
$(currentClass).css("padding-right", "20px");
}
else
$(currentClass).css("width", "187px");
$(currentClass).css("height", "187px");
$("article").css("float", "left");
$("article").css("margin", "11px");
$("span").css("display", "block");
$("span").css("padding-top", "167px");
$("span").css("padding-left", "12px");
}
//if (screen.width <= 480)
// $("#Interface").css("width", "470px");
//if (screen.width >= 1000 && screen.width <= 1799)
// $("#Interface").css("width", "470px");
//if (screen.width >= 1800)
// $("#Interface").css("width", "470px");
// This line below should be adding the random word to each of the articles
$('span').lorem({ type: 'words', amount: '1', ptags: false });
});
</script>
</head>
<body background = "Images/bg.png">
<div id="Interface"></div>
</body>
</html>
Now that I understand your problem, I propose to you start using css media queries. Basicaly for three reasons:
It's one way to solve your problem (duh)
This scripty resising and calculations will run slower when it comes to the real world.
It's much more clear and painless.
Make a css file with all rules that you want at determined screen size, then do this again for as many screen sizes you want to match. Remeber you can use all css tricks available to one determined screen size to achieve the look & feel that you want, because rules aplied under a media query will not mess with your css in other screen sizes.
After all, organize all the stylesheets in a single files and wrap them inside a proper media query.
Give it a try, you'll love it.
And yes, it's supported in at least the three earlier versions of IE, I guess.

JS not working in FireFox but works in Chrome & I.E

I know there are question like this but I still can't find a fix, I've looked through the console and can't see anything. There are two images, one which should appear on set coordinates, and another which follows the mouse, the one which is mean't to follow the mouse does not show up but the other one does.
Main.js
/**
* Created with JetBrains WebStorm.
* User: Script47
* Date: 22/09/13
* Time: 00:54
*/
function drawAvatars() {
// Create variable for the canvas & create a new object for image
var gameCanvas = document.getElementById("gameCanvas");
var userImage = new Image();
// The source of the images
userImage.src = ("Images/userImage.png");
// Create an event listener then call function redrawAvatar
gameCanvas.addEventListener("mousemove", redrawAvatar);
}
function redrawAvatar(mouseEvent) {
var gameCanvas = document.getElementById("gameCanvas");
var userImage = new Image();
var enemyImage = new Image();
var score = 0;
userImage.src = ("Images/userImage.png");
enemyImage.src = ("Images/enemyImage.png");
// Erase canvas sort of refresh, then re-draw image following the coordinates of the mouse in the canvas
gameCanvas.width = 400;
gameCanvas.getContext("2d").drawImage(userImage, mouseEvent.offsetX, mouseEvent.offsetY);
gameCanvas.getContext("2d").drawImage(enemyImage, 150, 150);
// Simple hit detection to see if user image hits enemy image
if (mouseEvent.offsetX > 130 && mouseEvent.offsetX < 175 && mouseEvent.offsetY > 130 && mouseEvent.offsetY < 175) {
score++;
alert("You hit the enemy!\n You score is: " +score);
}
}
Index.html
<!DOCTYPE html>
<html>
<head>
<title>Avoid Me | Game</title>
<link rel="stylesheet" type="text/css" href="CSS/styles.css">
<script src="JS/Main.js"></script>
</head>
<body>
<br/>
<center><h3>Avoid Me!</h3>
<br/>
<br/>
<canvas id="gameCanvas" height="300" width="400" onclick="drawAvatars();">
<p><strong>Notice:</strong> Browser does not support canvas!</p>
</canvas>
</center>
</body>
</html>
JsFiddle
(Basing this off the code in the link you provided.)
In your mouseMovement function, you use mouseEvent.offsetX and mouseEvent.offsetY to get the player's position, but Firefox unfortunately doesn't support those properties. Unfortunately, IIRC, the only thing that works cross-browser is to get the position of the canvas, and subtract it from the event's pageX/pageY properties. You can use the canvas's getBoundingClientRect() method to find its position on the page.
This is is an example of a version of the function that should work in Firefox as well:
function mouseMovement(mouseEvent) {
var canvasPosition = gameCanvas.getBoundingClientRect();
userImageX = mouseEvent.pageX - canvasPosition.left;
userImageY = mouseEvent.pageY - canvasPosition.top;
}

Stop animation in VivaGraph.JS

How I can stop the animation for the nodes in VivaGraph.JS
everything is great but nodes still moving and some nodes come out in the frame.
I can't use this example :
https://github.com/anvaka/VivaGraphJS/blob/master/demos/other/constantLayout.html
because is not good for me the determinate for every node a position.
My code :
<!DOCTYPE html>
<html>
<head>
<title>02. Custom node appearance. Vivagraph SVG tutorial.</title>
<script type="text/javascript" src="../../dist/vivagraph.js"></script>
<script type="text/javascript">
function main () {
// Create a graph:
var graph = Viva.Graph.graph();
for(i=0;i<20;i++)
{
graph.addNode(i, '91bad8ceeec43ae303790f8fe238164b');
}
var graphics = Viva.Graph.View.svgGraphics();
graphics.node(function(node) {
var url = 'https://secure.gravatar.com/avatar/' + node.data;
return Viva.Graph.svg('image')
.attr('width', 24)
.attr('height', 24)
.link(url);
});
graphics.placeNode(function(nodeUI, pos) {
nodeUI.attr('x', pos.x - 12).attr('y', pos.y - 12);
});
// Render the graph with our customized graphics object:
var renderer = Viva.Graph.View.renderer(graph, {
graphics : graphics
});
renderer.run();
}
</script>
<style type="text/css" media="screen">
html, body, svg { width: 100%; height: 100%;}
</style>
</head>
<body onload='main()'>
</body>
</html>
I wish I explain good my problem, someone can help me please.
You can use the following methods of the renderer object to accomplish this.
To start the rendering - renderer.run();
To pause the rendering - renderer.pause();
To resume the rendering - renderer.resume();
To reset the scale of the rendering to fit all elements - renderer.reset();
To remove the rendering - renderer.dispose();
Hope this is helpful...

Chrome leaks memory when simply adding and removing SVG elements

Continuing this question: Task manager shows memory leak, but Heap snapshot doesn't
I managed to create a very simple example, which illustrates this leak, here is full source code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>svg test</title>
<script type="text/javascript">
var svg;
var interval;
var svg;
window.onload = function(){
createSVG();
start();
}
function start(){
interval = setInterval(createElements, 100);
}
function createSVG(){
var div = document.getElementById("svgdiv");
div.innerHTML = "";
svg = createSvgElement("svg");
svg.style.position = "absolute";
svg.style.width = "600px";
svg.style.height = "500px";
svg.setAttribute("version", "1.1");
div.appendChild(svg);
createElements();
}
function createElements(){
removeElements();
for(var i = 0; i < 500; i++){
var element = createSvgElement("circle");
element.setAttribute("r", Math.random() * 10);
var transform = "translate(" + Math.round(Math.random() * 600) + "," + Math.round(Math.random() * 500) + ")";
element.setAttribute("transform", transform);
element.setAttribute("fill", "#CC0000");
svg.appendChild(element);
}
}
function removeElements(){
while(svg.hasChildNodes() ){
svg.removeChild(svg.lastChild);
}
}
function createSvgElement (name) {
return document.createElementNS("http://www.w3.org/2000/svg", name);
}
function stop(){
clearInterval(interval)
}
</script>
</head>
<body style="background-color:#FFFFFF">
<div id="svgdiv" style="width:600px; height:500px;"></div>
<input type="button" value="start" onclick="start()">
<input type="button" value="stop" onclick="stop()">
</body>
</html>
If I run this script, Chrome keeps eating the memory until it crashes. Other browsers don't. Instead of removing children one by one I also tried to clear it in a fast way by setting innerHTML="", but it's the same.
I enabled an experimental feature of Chrome which shows the kind of memory is used. The "Pages structures" memory is increasing a bit (however the HTML remains the same and there are no detached DOM objects), but the most memory goes to "Other" section.
If I stop the script and force GC to do it's job, the memory decreases by only few kilobytes. However if I wait for a minute or two, the memory is cleaned almost to a initial level. I know that my script is quite intense, but this happens also if I run it every 1 or two seconds only - I think that's quite enough for GC to do it's job. And I know GC is working, as other kind of memory is released. Could this be a Chrome bug? Maybe I should do something before removing the elements?
I managed to slow it down but it is still leaking. I also recreated the test using Raphael.js which did not leak. But when I was testing I found that it was when it was appending the circles. So Raphael must be doing something to stop it from leaking at that point.
Not sure, if it would be of much help, but if you define "var svg" only once,
then memory-consumption ( in Task manager) is not rising that fast
and also stop() function does work after that
This was indeed bug in Chrome, which was fixed some time later:
https://bugs.chromium.org/p/chromium/issues/detail?id=172221&can=4&q=svg&colspec=ID%20Pri%20Mstone%20ReleaseBlock%20OS%20Area%20Feature%20Status%20Owner%20Summary

Categories

Resources