Related
sorry for the amatuer question, I'm really new to Pixi.js
Well, I'm trying to make a scratch card.
There will be two image, one for background("A"), and one for hidden background( "B" , I think this is mask, but I'm not sure about this terminology , so to avoid confusion I'll describe as hidden background)
So, image 'A' will cover up image 'B'.
Then, I'will use bristle image for the brush.
When I execute dragging event on Image "A" , I want to show up image 'B" along path mouse moved.
Sorry , for my terrible description. Think I'm cloning this website ( https://art4globalgoals.com/en )
I followed this example( https://pixijs.io/examples/#/demos-advanced/scratchcard.js ), and succeed to make a brush effect, with only 1 image. But couldn't implement it with two image.
Precisely speaking , when I run my app, there is black screen rendered , and if I scratch screen, the hidden Image appears.
but the problem is that, I want to set other Image instead of black screen.
below image is my current status , which will happen when running below code
import * as PIXI from 'pixi.js';
// const canvas = document.getElementById('webgl');
const screenSize = {
width: window.innerWidth,
height: window.innerHeight
};
let brushWidth = (window.innerHeight / window.innerWidth) * 200;
let brushHeight = (window.innerHeight / window.innerWidth) * 200;
// canvas.width = screenSize.width;
// canvas.height = screenSize.height;
const app = new PIXI.Application({
width: window.innerWidth,
height: window.innerHeight,
resolution: window.devicePixelRatio,
autoDensity: true
});
document.body.appendChild(app.view);
app.loader
.add('background', '/png/effel.png')
.add('mask', '/png/effel-gray.png')
.add('bristle1', '/png/brush6.png')
.add('bristle2', '/png/bristle2.png')
.load(() => {
setup();
});
const setup = () => {
const brushTexture = app.loader.resources.bristle1.texture;
const brushTexture2 = app.loader.resources.bristle2.texture;
const brush = new PIXI.Sprite(brushTexture);
const brush2 = new PIXI.Sprite(brushTexture2);
brush.width = brushWidth;
brush.height = brushHeight;
brush2.width = brushWidth;
brush2.height = brushHeight;
const backgroundTexture = app.loader.resources.background.texture;
const maskTexture = app.loader.resources.mask.texture;
const background = new PIXI.Sprite(backgroundTexture);
background.x = app.renderer.screen.width / 2;
background.y = app.renderer.screen.height / 2;
background.anchor.x = 0.5;
background.anchor.y = 0.5;
background.width = window.innerWidth;
background.height = window.innerHeight;
const Mask = new PIXI.Sprite(maskTexture);
Mask.width = app.renderer.screen.width;
Mask.height = app.renderer.screen.height;
Mask.x = app.renderer.screen.width / 2;
Mask.y = app.renderer.screen.height / 2;
Mask.anchor.x = 0.5;
Mask.anchor.y = 0.5;
Mask.width = window.innerWidth;
Mask.height = window.innerHeight;
// app.stage.addChild(background);
app.stage.addChild(Mask);
const renderTexture = PIXI.RenderTexture.create(app.screen.width, app.screen.height);
const renderTextureSprite = new PIXI.Sprite(renderTexture);
app.stage.addChild(renderTextureSprite);
Mask.mask = renderTextureSprite;
app.stage.interactive = true;
app.stage.on('pointerdown', pointerDown);
app.stage.on('pointerup', pointerUp);
app.stage.on('pointermove', pointerMove);
let dragging = false;
let bristle2Render = false;
function pointerMove(event) {
if (dragging) {
brush.position.copyFrom(event.data.global);
// brushWidth += 0.5;
// brush.width = brushWidth;
if (!bristle2Render) {
setTimeout(() => (bristle2Render = true), 500);
}
app.renderer.render(brush, renderTexture, false, null, false);
if (bristle2Render) {
brush2.position.copyFrom(event.data.global);
app.renderer.render(brush2, renderTexture, false, null, false);
}
// if (brush.width === 100) {
// dragging = false;
// brushWidth = 0;
// }
}
}
function pointerDown(event) {
dragging = true;
console.log(11);
pointerMove(event);
}
function pointerUp(event) {
dragging = false;
bristle2Render = false;
}
window.addEventListener('resize', () => {
screenSize.width = window.innerWidth;
screenSize.height = window.innerHeight;
app.renderer.resize(window.innerWidth, window.innerHeight);
app.renderer.stage.width = window.innerWidth;
app.renderer.stage.height = window.innerHeight;
});
};
// const backgroundTexture = PIXI.Texture.from('/png/effel.png');
// const maskTexture = PIXI.Texture.from('/png/effel-gray.png');
I guess the problem is that you haven't added background to the stage, because you commented it.
// app.stage.addChild(background);
app.stage.addChild(Mask);
So, there is nothing to be shown at the beginning, so it is a black screen.
Here is a CodePen that I created. I removed some comments and replaced the resources with some other images. It should be somehow working after you uncommented the line.
By the way, you may want to ensure that:
your variables have a capital name only for some special reasons (e.g. Mask)
you don't overwrite values that you have set before (e.g. Mask.width = ...).
Although the code still works without fixing the above, this may make the code harder to work with for others, including a future "you". ;)
When your code works, you may want to post it on Code Review to see how to improve the code.
I am writing code to maintain same strokeWidth across all the objects in Fabricjs.
I am able to successfully maintain strokeWidth for normal Objects , let it be rectangle or ellipse(I wrote code to maintain both).
But when I use group , I am unable to maintain the strokeWidth.
Here's the fiddle.
Steps to reproduce the issue ?
1)Open above fiddle link
2)resize the circle , check the size of border (thickness of border remains the same on re-sizing)
3)Now resize the rectangle and text(group) , expected result is thickness of border must be same throughout but that doesn't happens.
Code :
`
var gCanvas = new fabric.Canvas('canvDraw');
gCanvas.setWidth(700);
gCanvas.setHeight(700);
var text = new fabric.Text('test', { fontSize: 30, top: 100, left : 100, fill : 'red'});
// add some shapes - these are examples, others should work too
var myRectangle = new fabric.Rect({
left: 100,
top: 100,
fill: '#999999',
width: 120,
height: 120,
strokeWidth: 3,
fill: '',
stroke: '#000000'
});
var group = new fabric.Group([ myRectangle, text ], {borderColor: 'black', cornerColor: 'green', lockScalingFlip : true});
gCanvas.add(group);
var myEllipse = new fabric.Ellipse({
top: 250,
left: 100,
rx: 75,
ry: 50,
fill: '',
stroke: '#000000',
strokeWidth: 3
});
gCanvas.add(myEllipse);
gCanvas.observe('object:scaling', function (e) {
e.target.resizeToScale();
});
fabric.Object.prototype.resizeToScale = function () {
// resizes an object that has been scaled (e.g. by manipulating the handles), setting scale to 1 and recalculating bounding box where necessary
switch (this.type) {
case "ellipse":
this.rx *= this.scaleX;
this.ry *= this.scaleY;
this.width = this.rx * 2;
this.height = this.ry * 2;
this.scaleX = 1;
this.scaleY = 1;
break;
case "rect":
this.width *= this.scaleX;
this.height *= this.scaleY;
this.scaleX = 1;
this.scaleY = 1;
default:
break;
}
}
`
this approach will not work for all kind of shapes. when facing text or polygons you cannot recalculate everything.
you can do something like that:
fabric.Object.prototype.resizeToScale = function () {
if (this.type !=='group') {
this.strokeWidth = this._origStrokeWidth / Math.max(this.scaleX, this.scaleY);
}
else {
this._objects.forEach( function(obj){
console.log(obj);
obj.strokeWidth = obj._origStrokeWidth / Math.max(obj.group.scaleX, obj.group.scaleY);
});
}
}
if you prefer the effect of your solution (border is always uniform) put this line of code in the default case of your switch construct to handle all the types for wich you cannot find a resizing solution.
edit i added group handling.
The point is to make smaller strokewidth when the group / object scale.
Because when you will have polygons and polylines and paths, changing width / height /radius will not help.
http://jsfiddle.net/y344vs5s/4/
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I have been doing a little experimenting with canvas, creating drawings using lines shapes text etc, and inserting .png files. The inserting .png files is the bit that I cannot get to work.
Edit:
Undesired behaviour of this code: I load shapes to the graphics context, then load an image file to the graphics context, however when the graphics context is drawn, the image is at behind the shapes, despite being drawn last.
I wanted the image file to be at the top, in front of the shapes.
Desired behaviour: To bring image file to the front of the canvas, so it is not hidden by shapes drawn in the graphics context.
function loadImage(name) {
images[name] = new Image();
images[name].src = "DogWalking/" + name + ".png";
images[name].onload = function() {
graphics.drawImage(this, 0, 300);
canvas.bringToFront(this);
};
}
the function for drawing is called here:
function draw() {
graphics.save(); // to make sure changes don't carry over from one call to the next
graphics.fillStyle = "transparent"; // background color
graphics.fillRect(0,0,wWidth, wHeight);
graphics.fillStyle = "black";
applyLimits(graphics,xleft,xright,ytop,ybottom,true);
graphics.lineWidth = pixelSize;
world.draw(graphics);
graphics.drawImage(images["dog-walking11"],200,200);
graphics.restore();
}
code for the whole page is
<!DOCTYPE html>
<html>
<meta charset="UTF-8">
<head>
<title>Hierarchical Modeling 2D</title>
<style>
#messagediv {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 0;
background-color: indigo;
}
#canvasdiv {
position: absolute;
left: 0;
top: 0;
z-index: 10;
background-color: transparent;
}
</style>
<script type="text/javascript" src="rgbcolor.js"></script>
<script type="text/javascript">
"use strict";
var totalResources = 17;
var numResourcesLoaded = 0;
var images = {};
function loadImage(name) {
images[name] = new Image();
images[name].src = "DogWalking/" + name + ".png";
images[name].onload = function() {
//
graphics.drawImage(this, 0, 300);
canvas.bringToFront(this);
}
}
var canvas; // DOM object corresponding to the canvas
var graphics; // 2D graphics context for drawing on the canvas
var ctx; // 2D graphics context for drawing on the canvas
var myNumber = 0, myNumber2 = 0, myInterval, myInterval2, myelement, thisdiv, printx;
var mycoords = new Array();
var pcoords = new Array(); //coordinates of the portal.
//var pcoords = [[0,0], [50,300], [250,150]]; //coordinates of the portal.
var nocoords = 2;
var frameNumber = 0; // Current frame number.
var frameNumber2 = 0;
var sun;
var sun2;
var ground;
var world;
var pixelSize;
var wWidth;
var wHeight;
var portals = new Array("calendar1","alternativsearch","art1", "directory1");
var portalsval = new Array();
var portalsobj;
var leftj = new Array(3,1,4,2);
var forwards = "http://www.alternativworld.com";
// ---------------- Set Page Layout ----------------
// function to set size of canvas and location of portals
function pageLayout() {
var w = window, d = document, e = d.documentElement, g = d.getElementsByTagName('body')[0];
wWidth = w.innerWidth || e.clientWidth || g.clientWidth;
wHeight = w.innerHeight|| e.clientHeight|| g.clientHeight;
// Adjust wWidth and wHeight if ratio does not match scenary 7 by 5.
if (wWidth/wHeight != 7/5)
if (wWidth/wHeight > 7/5) {
var widthPortion = 5 * wWidth/wHeight;
wWidth = wWidth * 7 / widthPortion;
} else {
var heightPortion = 7 * wHeight/wWidth;
wHeight = wHeight * 5 / heightPortion;
}
var widthheight, localerror = false;
widthheight = Math.min(wWidth, wHeight);
if(widthheight < 400){
var localerror = true;
}
if (localerror == true)
alert("Warning, the page size of your browser or your screen resolution may be too small to correctly view this web page.");
var theCanvas = d.getElementById("theCanvas");
theCanvas.height = wHeight;
theCanvas.width = wWidth;
}
//Function to listen to the mouse events and see if a link is selected.
function doMouseDown(evt) {
var r = canvas.getBoundingClientRect();
var x = Math.round(evt.clientX - r.left);
var y = Math.round(evt.clientY - r.top);
alert(evt.clientX+ " " + evt.clientY);
for (var i = portals.length+1; i >= 0; i--) {
var p = pcoords[i];
if (Math.abs(p[0] - x) <= 50 && Math.abs(p[1] - y) <= 50) {
document.location.href = forwards;
return;
} else if (Math.abs(0 - x) <= 50 && Math.abs(0 - y) <= 50){
document.location.href = "http://www.alternativeuk.co.uk";
return;
}
}
}
// ---------------- The object-oriented scene graph API ------------------
/**
* The base class for all nodes in the scene graph data structure.
*/
function SceneGraphNode() {
this.fillColor = null; // If non-null, the default fillStyle for this node.
this.strokeColor = null; // If non-null, the default strokeStyle for this node.
}
SceneGraphNode.prototype.doDraw = function(g) {
// This method is meant to be abstract and must be
// OVERRIDDEN in any actual object in the scene graph.
// It is not meant to be called; it is called by draw().
throw "doDraw not implemented in SceneGraphNode"
}
SceneGraphNode.prototype.draw = function(g) {
// This method should be CALLED to draw the object
// represented by this SceneGraphNode. It should NOT
// ordinarily be overridden in subclasses.
graphics.save();
if (this.fillColor) {
g.fillStyle = this.fillColor;
}
if (this.strokeColor) {
g.strokeStyle = this.strokeColor;
}
this.doDraw(g);
graphics.restore();
}
SceneGraphNode.prototype.setFillColor = function(color) {
// Sets fillColor for this node to color.
// Color should be a legal CSS color string, or null.
this.fillColor = color;
return this;
}
SceneGraphNode.prototype.setStrokeColor = function(color) {
// Sets strokeColor for this node to color.
// Color should be a legal CSS color string, or null.
this.strokeColor = color;
return this;
}
SceneGraphNode.prototype.setColor = function(color) {
// Sets both the fillColor and strokeColor to color.
// Color should be a legal CSS color string, or null.
this.fillColor = color;
this.strokeColor = color;
return this;
}
/**
* Defines a subclass, CompoundObject, of SceneGraphNode to represent
* an object that is made up of sub-objects. Initially, there are no
* sub-objects.
*/
function CompoundObject() {
SceneGraphNode.call(this); // do superclass initialization
this.subobjects = []; // the list of sub-objects of this object
}
CompoundObject.prototype = new SceneGraphNode(); // (makes it a subclass!)
CompoundObject.prototype.add = function(node) {
// Add node a subobject of this object. Note that the
// return value is a reference to this node, to allow chaining
// of method calls.
this.subobjects.push(node);
return this;
}
CompoundObject.prototype.doDraw = function(g) {
// Just call the sub-objects' draw() methods.
for (var i = 0; i < this.subobjects.length; i++)
this.subobjects[i].draw(g);
}
/**
* Define a subclass, TransformedObject, of SceneGraphNode that
* represents an object along with a modeling transformation to
* be applied to that object. The object must be specified in
* the constructor. The transformation is specified by calling
* the setScale(), setRotate() and setTranslate() methods. Note that
* each of these methods returns a reference to the TransformedObject
* as its return value, to allow for chaining of method calls.
* The modeling transformations are always applied to the object
* in the order scale, then rotate, then translate.
*/
function TransformedObject(object) {
SceneGraphNode.call(this); // do superclass initialization
this.object = object;
this.rotationInDegrees = 0;
this.scaleX = 1;
this.scaleY = 1;
this.translateX = 0;
this.translateY = 0;
}
TransformedObject.prototype = new SceneGraphNode(); // (makes it a subclass!)
TransformedObject.prototype.setRotation = function(angle) {
// Set the angle of rotation, measured in DEGREES. The rotation
// is always about the origin.
this.rotationInDegrees = angle;
return this;
}
TransformedObject.prototype.setScale = function(sx, sy) {
// Sets scaling factors.
this.scaleX = sx;
this.scaleY = sy;
return this;
}
TransformedObject.prototype.setTranslation = function(dx,dy) {
// Set translation mounts.
this.translateX = dx;
this.translateY = dy;
return this;
}
TransformedObject.prototype.doDraw = function(g) {
// Draws the object, with its modeling transformation.
g.save();
if (this.translateX != 0 || this.translateY != 0) {
g.translate(this.translateX, this.translateY);
}
if (this.rotationInDegrees != 0) {
g.rotate(this.rotationInDegrees/180*Math.PI);
}
if (this.scaleX != 1 || this.scaleY != 1) {
g.scale(this.scaleX, this.scaleY);
}
this.object.draw(g);
g.restore();
}
/**
* A subclass of SceneGraphNode representing filled triangles.
* The constructor specifies the vertices of the triangle:
* (x1,y1), (x2,y2), and (x3,y3).
*/
function Triangle(x1,y1,x2,y2,x3,y3) {
SceneGraphNode.call(this);
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.x3 = x3;
this.y3 = y3;
}
Triangle.prototype = new SceneGraphNode();
Triangle.prototype.doDraw = function(g) {
g.beginPath();
g.moveTo(this.x1,this.y1);
g.lineTo(this.x2,this.y2);
g.lineTo(this.x3,this.y3);
g.closePath();
g.fill();
}
/**
* Directly create a line object as a SceneGraphNode with a
* custom doDraw() method. line is of length 1 and
* extends along the x-axis from (0,0) to (1,0).
*/
var line = new SceneGraphNode();
line.doDraw = function(g) {
g.beginPath();
g.moveTo(0,0);
g.lineTo(1,0);
g.stroke();
}
/**
* Directly create a filled rectangle object as a SceneGraphNode with a
* custom doDraw() method. filledRect is a square with side 1, centered
* at (0,0), with corners at (-0.5,-0.5) and (0.5,0.5).
*/
var filledRect = new SceneGraphNode();
filledRect.doDraw = function(g) {
g.fillRect(-0.5,-0.5,1,1);
}
/**
* Directly create a rectangle object as a SceneGraphNode with a
* custom doDraw() method. rect is a square with side 1, centered
* at (0,0), with corners at (-0.5,-0.5) and (0.5,0.5). Only the
* outline of the square is drawn.
*/
var rect = new SceneGraphNode();
rect.doDraw = function(g) {
g.strokeRect(-0.5,-0.5,1,1);
}
/**
* Directly create a filled circle object as a SceneGraphNode with a
* custom doDraw() method. filledCircle is a circle with radius 0.5
* (diameter 1), centered at (0,0).
*/
var filledCircle = new SceneGraphNode();
filledCircle.doDraw = function(g) {
g.beginPath();
g.arc(0,0,0.5,0,2*Math.PI);
g.fill();
}
var clickHere = new SceneGraphNode();
clickHere.doDraw = function(g) {
g.fillText("click here :)",0,0)
}
/**
* Directly create a circle object as a SceneGraphNode with a
* custom doDraw() method. filledCircle is a circle with radius 0.5
* (diameter 1), centered at (0,0). Only the outline of the circle
* is drawn.
*/
var circle = new SceneGraphNode();
circle.doDraw = function(g) {
g.beginPath();
g.arc(0,0,0.5,0,2*Math.PI);
g.stroke();
}
var dog = new SceneGraphNode();
dog.doDraw = function(g) {
g.drawImage(images["dog-walking11"],-2, 2);
alert(images["dog-walking11"].name);
}
// -------------------- Specific to this application ----------------------------
/*
* Define two extra basic objects as SceneGraphNodes with custom doDraw() methods.
* One represents the ground, the other a vane for a windmill.
*/
var ground = new SceneGraphNode();
ground.doDraw = function(g) {
g.beginPath();
g.moveTo(0,-1);
g.lineTo(0,0.8);
g.lineTo(1.5,1.65);
g.lineTo(1.8,1.3);
g.lineTo(3,2.1);
g.lineTo(4.7,0.7);
g.lineTo(6.1,1.2);
g.lineTo(7,0.8);
g.lineTo(7,-1);
g.closePath();
g.fill();
}
var windmillVane = new SceneGraphNode();
windmillVane.doDraw = function(g) {
g.beginPath();
g.moveTo(0,0);
g.lineTo(0.5,0.1);
g.lineTo(1.5,0);
g.lineTo(0.5,-0.1);
g.closePath();
g.fill();
}
var world; // A SceneGraphNode representing the entire picture. This should
// be created in the createWorld() method.
var pixelSize; // The size of one pixel, in the transformed coordinates.
// This is used as the default width of a stroke.
var background = "#C8C8FF"; // A CSS color string giving the background color.
// the draw() function fills the canvas with this color.
var xleft = 0; // The requested xy-limits on the canvas, after the
var xright = 7; // coordinate transformation has been applied.
var ybottom = -1; // The transformation is applied in the draw() function.
var ytop = 4;
var frameNumber = 0; // Current frame number.
var cart; // TransformedObjects that are animated.
var wheel;
var sun;
var clickText1;
var clickText2;
var rotor;
/**
* Create the scene graph data structure. The global variable world must
* refer to the root node of the scene graph. This function is called in
* the init() function.
*/
function createWorld() {
pageLayout();
var i;
var sunTemp = new CompoundObject();
sunTemp.setColor("yellow"); // color for filled circle and light rays
for (i = 0; i < 12; i++) { // add the 12 light rays, with different rotations
sunTemp.add( new TransformedObject(line).setScale(0.75,0.75).setRotation(i*30) );
}
sunTemp.add( filledCircle ); // the face of the sun
sunTemp.add( new TransformedObject(circle).setColor("#B40000") ); // outlines the face
sun = new TransformedObject(sunTemp);
clickText1 = new TransformedObject(clickHere).setColor("#B40000").setScale(0.01,-0.01);
var wheelTemp = new CompoundObject();
wheelTemp.setColor("black"); // color for all but one of the subobjects
wheelTemp.add( new TransformedObject(filledCircle).setScale(2,2) );
wheelTemp.add( new TransformedObject(filledCircle).setScale(1.6,1.6).setColor("#CCCCCC") );
wheelTemp.add( new TransformedObject(filledCircle).setScale(0.4,0.4) );
for (i = 0; i < 12; i++) { // add the 12 spokes
wheelTemp.add( new TransformedObject(line).setRotation(i*30) );
}
wheel = new TransformedObject(wheelTemp);
var cartTemp = new CompoundObject();
cartTemp.setColor("red"); // color for the rectangular body of the cart
cartTemp.add( new TransformedObject(wheel).setScale(0.8,0.8).setTranslation(1.5,-0.1) );
cartTemp.add( new TransformedObject(wheel).setScale(0.8,0.8).setTranslation(-1.5,-0.1) );
cartTemp.add( new TransformedObject(filledRect).setScale(5,2).setTranslation(0,1) ); // the body of the cart
cart = new TransformedObject(cartTemp).setScale(0.3,0.3);
clickText2 = new TransformedObject(clickHere).setColor("yellow").setScale(0.01,-0.01);
var rotorTemp = new CompoundObject(); // a "rotor" consisting of three vanes
rotorTemp.setColor( "#C86464" ); // color for all of the vanes
rotorTemp.add( windmillVane );
rotorTemp.add( new TransformedObject(windmillVane).setRotation(120) );
rotorTemp.add( new TransformedObject(windmillVane).setRotation(240) );
rotor = new TransformedObject(rotorTemp);
var windmill = new CompoundObject();
windmill.setColor("#E0C8C8"); // color for the pole
windmill.add( new TransformedObject(filledRect).setScale(0.1,3).setTranslation(0,1.5) ); // the pole
windmill.add( new TransformedObject(rotor).setTranslation(0,3) ); // the rotating vanes
world = new CompoundObject();
world.setColor("#00961E"); // color used for the ground only
world.add(ground);
//world.add( new TransformedObject(filledRect).setScale(7,0.8).setTranslation(3.5,0).setColor("#646496") ); // road
//world.add( new TransformedObject(filledRect).setScale(7,0.06).setTranslation(3.5,0).setColor("white") ); // line in road
world.add( new TransformedObject(windmill).setScale(0.6,0.6).setTranslation(0.75,1) );
world.add( new TransformedObject(windmill).setScale(0.4,0.4).setTranslation(2.2,1.3) );
world.add( new TransformedObject(windmill).setScale(0.7,0.7).setTranslation(3.7,0.8) );
world.add( new TransformedObject(sun).setTranslation(5.5,3.3) );
world.add( new TransformedObject(clickText1).setTranslation(5.25,3.3) );
world.add( cart );
world.add( clickText2 );
//alert(2);
}
/**
* This will be called before each frame is drawn.
*/
function updateFrame() {
frameNumber++;
if (frameNumber>= 312){
frameNumber = 0;
frameNumber2 = 1;
}
cart.setTranslation(-3 + 13*(frameNumber % 300) / 300.0, 0);
clickText2.setTranslation(-3.3 + 13*(frameNumber % 300) / 300.0, 0.25);
if (typeof(pcoords[5]) != 'undefined') {
pcoords[5][0] = (-3.3 + 13*(frameNumber % 300) / 300.0-xleft)*canvas.width / (xright-xleft);
pcoords[5][1] = (0.25-ytop)*canvas.height / (ybottom-ytop);
}
wheel.setRotation(-frameNumber*3.1);
sun.setRotation(-frameNumber);
rotor.setRotation(frameNumber * 2.7);
}
// ------------------------------- graphics support functions --------------------------
/**
* Draw one frame of the animation. Probably doesn't need to be changed,
* except maybe to change the setting of preserveAspect in applyLimits().
*/
function draw() {
graphics.save(); // to make sure changes don't carry over from one call to the next
graphics.fillStyle = "transparent"; // background color
graphics.fillRect(0,0,wWidth, wHeight);
graphics.fillStyle = "black";
applyLimits(graphics,xleft,xright,ytop,ybottom,true);
graphics.lineWidth = pixelSize;
world.draw(graphics);
graphics.drawImage(images["dog-walking11"],200,200);
graphics.restore();
}
/**
* Applies a coordinate transformation to the graphics context, to map
* xleft,xright,ytop,ybottom to the edges of the canvas. This is called
* by draw(). This does not need to be changed.
*/
//pcoords[0][0] =
//pcoords[0][1]=
function applyLimits(g, xleft, xright, ytop, ybottom, preserveAspect) {
var width = canvas.width; // The width of this drawing area, in pixels.
var height = canvas.height; // The height of this drawing area, in pixels.
var k = portals.length;
var j;
var i = 0, widthheight, myradius;
var localerror = false;
if (pcoords.length < k) {
while (portals[i]){
j = i + 1;
if (width > 100){
var rWidth = width/(k + 1);
rWidth= Math.floor(rWidth);
} else {
var lWidth = 0;
var rWidth = 0;
}
if (height > 100){
var bHeight = height/(k + 1);
bHeight= Math.floor(bHeight);
} else {
var tHeight = 0;
var bHeight = 0;
}
var myleft = leftj[i] * rWidth - 50;
var mytop = j * bHeight - 50;
pcoords[i]= new Array;
pcoords[i][0] = myleft;
pcoords[i][1] = mytop;
i = i + 1;
}
}
if (preserveAspect) {
// Adjust the limits to match the aspect ratio of the drawing area.
var displayAspect = Math.abs(height / width);
var requestedAspect = Math.abs(( ybottom-ytop ) / ( xright-xleft ));
var excess;
if (displayAspect > requestedAspect) {
excess = (ybottom-ytop) * (displayAspect/requestedAspect - 1);
ybottom += excess/2;
ytop -= excess/2;
}
else if (displayAspect < requestedAspect) {
excess = (xright-xleft) * (requestedAspect/displayAspect - 1);
xright += excess/2;
xleft -= excess/2;
}
}
var pixelWidth = Math.abs(( xright - xleft ) / width);
var pixelHeight = Math.abs(( ybottom - ytop ) / height);
pixelSize = Math.min(pixelWidth,pixelHeight);
if (frameNumber == 4 || frameNumber == 5){
pcoords.push([(5.25-xleft)*width / (xright-xleft),(3.3-ytop)*height / (ybottom-ytop)]);
pcoords.push([(-3.3 + 13*(frameNumber % 300) / 300.0-xleft)*width / (xright-xleft), (0.25-ytop)*height / (ybottom-ytop)]);
}
g.scale( width / (xright-xleft), height / (ybottom-ytop) );
g.translate( -xleft, -ytop );
// if (frameNumber < 3)
}
//------------------ Animation framework ------------------------------
var animationTimeout = null; // A null value means the animation is off.
// Otherwise, this is the timeout ID.
function frame() {
// Draw one frame of the animation, and schedule the next frame.
updateFrame();
draw();
canvas.addEventListener("mousedown", doMouseDown, false);
animationTimeout = setTimeout(frame, 33);
}
function setAnimationRunning(run) {
if ( run ) {
if (animationTimeout == null) {
// If the animation is not already running, start
// it by scheduling a call to frame().
animationTimeout = setTimeout(frame, 33);
}
}
else {
if (animationTimeout != null) {
// If the animation is running, stop it by
// canceling the next scheduled call to frame().
clearTimeout(animationTimeout);
}
animationTimeout = null; // Indicates that animation is off.
}
}
//----------------------- initialization -------------------------------
function init() {
try {
canvas = document.getElementById("theCanvas");
if(typeof G_vmlCanvasManager != 'undefined') {
canvas = G_vmlCanvasManager.initElement(canvas);
}
graphics = canvas.getContext("2d");
}
catch (e) {
document.getElementById("message").innerHTML =
"Sorry, this page requires canvas graphics, but<br>" +
"it looks like your browser does not support it<br>" +
"Reported error: " + e;
return;
}
// add any other necessary initialization
document.getElementById("animateCheck").checked = true; // Make sure box is checked!
loadImage("dog-walking11");
createWorld();
setAnimationRunning(true); // start the animation
}
</script>
</head>
<body onload="init()" style="background-color: rgb(220,220,220)">
<div id="messagediv">
<h2>Hierarchical Modeling Example</h2>
<!-- For error reporting: the contents of the noscript tag are
shown only if JavaScript is not available. The paragraph with
id="message" is for reporting errors using JavaScript.-->
<noscript><b>This page requires JavaScript, which is<br>
not enabled in your browser.</b></noscript>
<p id="message" style="color:red"></p>
<p><input type="checkbox" id="animateCheck" onchange="setAnimationRunning(this.checked)">
<label for="animateCheck">Run Animation</label>
</p>
</div>
<div id="canvasdiv">
<canvas id="theCanvas" width= "400" height= "300"
style="background-color: transparent"></canvas>
</div>
</body>
</html>
It seems that I had to use graphics.drawImage() after using graphics.restore().
Though I was trying to draw the image in the correct order (after), compared to drawing the rectangles, circles etc, the shapes did not come out of the buffer onto the page until after the restore function().
When I was calling drawImage, I assumed that it was loading it onto the buffered canvas with the rest of the things, ready to be drawn in the correct order, when in fact it was putting it straight onto the page.
It seems strange since it was being called with the graphics context, so I thought it would be added to the rest of the canvas graphics, but i appear to be wrong.
Is there any option to increase bar chart as animation from 0 to ?
bars.animate({'stroke':"#FF0"},1000); this can change attributes. Actually I need to change value of bar chart height and also change label when increase which didn't find yet.
var svgWidth = 400;
var svgHeight = 450;
var r = Raphael('overview');
var barBorder = {stroke: '#000', 'stroke-width':1};
r.setViewBox(0, 0, svgWidth, svgHeight, false);
r.setSize('100%', '100%');
var colors = [ "#999", "#B2B2B2", "#CCC"];
data4 = [[83], [72], [43]];
data2 = [[13], [22], [20]];
var bars = r.barchart(50, 20, 250, 150, data4, {colors: colors, 'gutter': '-1%'}).bars.attr(barBorder);//.hover(fin, fout);
var unicorn = r.path("M350 150 H10 V10").attr({stroke: "#000","stroke-width": 1});
bars.animate({'stroke':"#FF0"},1000);
Demo.
Finally changed barchart() to rect()
here is my solution http://jsfiddle.net/sweetmaanu/sqnXM/
// Create options object that specifies the rectangle
var PatientBar1 = { width: 100,height: 200,x: 0,y: 0}
var PatientBar2 = { width: 100,height: 180,x: 100,y: 20}
var PatientBar3 = { width: 100,height: 120,x: 200,y: 80}
var speed = 2000;
// Create new raphael object
var patient01 = new Raphael('patient02-mobile', 300, 300);
/*
* Create rectangle object with y-position at bottom by setting it to the specified height,
* also give the rectangle a height of '0' to make it invisible before animation starts
*/
var rect1 = patient01.rect(PatientBar1.x, PatientBar1.height, PatientBar1.width, 0).attr({fill: '#999', stroke:'#000'});
var rect2 = patient01.rect(PatientBar2.x, 200, PatientBar2.width, 0).attr({fill: '#B2B2B2', stroke:'#000'});
var rect3 = patient01.rect(PatientBar3.x, 200, PatientBar3.width, 0).attr({fill: '#CCC', stroke:'#000'});
/*
* Animate the rectangle from bottom up by setting the height to the earlier specified
* height and by setting the y-position to the top of the rectangle
*/
var anim1 = rect1.animate({
y:PatientBar1.y,
height:PatientBar1.height
}, speed);
var anim2 = Raphael.animation({
y:PatientBar2.y,
height:PatientBar2.height
}, speed);
var anim3 = Raphael.animation({
y:PatientBar3.y,
height:PatientBar3.height
}, speed);
rect2.animate(anim2.delay(2000));
rect3.animate(anim3.delay(4000));
Please post answer if anybody find solution :)
I want to draw image sprite using canvas.
The code not working. How to improve my code.
I have some Error.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var Game = {
draw_image: function(img, sourceX, sourceY, sourceW, sourceH, destX, destY, destW, destH){
var img = new Image(); // Create new img element
img.src = 'images/background.png'; // Set source path
img.onload = function(){
canvas.width = 1000;
canvas.height = 500;
ctx.drawImage(img, sourceX, sourceY, sourceW, sourceH, destX, destY, destW, destH);
};
}
var BACKGROUND = {
image_top: { x: 5, y: 5, w: 1280, h: 480 , dx:0 ,dy:0 ,dw:500 ,dh:500 },
image_body: { x: 5, y: 495, w: 1280, h: 480 , dx:0 ,dy:150 ,dw:500 ,dh:350},
image_bottom: { x: 5, y: 985, w: 1280, h: 480 , dx:0 ,dy:300 ,dw:500 ,dh:200 }
};
for(var n = 0 ; n < BACKGROUND.length ; n++) {
draw_image(nameImage, BACKGROUND[n].x,BACKGROUND[n].y, BACKGROUND[n].w, BACKGROUND[n].h, BACKGROUND[n].dx, BACKGROUND[n].dy, BACKGROUND[n].dw, BACKGROUND[n].dh );
}
};
To create a sprite animation it's important to know how it works.
You need your spritesheet make with pixel precision ( 1 pixel can mess up your animation ).
Like here, the character is always in the same size area, make it simple when you make your sprites.
With this you can make an object for each sprite you have like :
function Sprite(_position, _numberFrame, _framesize, _image, _duration){
this.position = _position; //Array like { x : 0, y : 0 }
this.rendersize = _rendersize; //Array like { width : 50, height : 80 }
this.framesize = _framesize; //Array like { width : 50, height : 80 }
this.image = _image; //Image object
this.chrono = new Chrono(_duration); //Explanation below
}
For more animation precision you can add a chrono who will manage the time of your animation :
function Chrono(_duration){
this.currentTime = 0;
this.lastTime = 0;
this.timeElapse = 0;
this.duration = _duration;
}
Chrono.prototype.countTime = function(){
this.currentTime = Date.now();
if(this.lastTime != 0)
this.timeElapse += this.currentTime - this.lastTime;
this.lastTime = Date.now();
if(this.timeElpase >= this.duration && this.lastTime != 0){
this.timeElapse = 0;
return TRUE;
} else {
return FALSE;
}
}
Then the function to animate your sprite may like :
Sprite.prototype.render = function(){
if(this.position.x <= this.image.width && this.chrono.countTime()){
this.position.x += this.framesize.x;
} else {
this.position.x = 0;
}
ctx.drawImage(this.image,
this.position.x, this.position.y,
this.framesize.width, this.framesize.height,
this.rendersize.width, this.rendersize.height
);
}
I hope I was clear and helpful,
Cheers
PS: Comments for question or optimisation ideas
You have to many problems with this code to make this sprite animation works. I wouldn't go to point any of the problems with your code, but I highly recommend to read a little bit about functions and variable scope before try to write this kind of code.
Another simple (and best for newbies) solution can be to use a canvas framework as EaselJS, with this you can do something like this to animate an sprite:
var data = {
images: ["images/background.png"],
frames: {width:50, height:50},
animations: {run:[0,4], jump:[5,8,"run"]}
};
var animation = new createjs.BitmapAnimation(data);
animation.gotoAndPlay("run");