Chebyshev distance x coordinate bugs when moving - javascript

So I was replicating the Phaser Chebyshev Distance example, And After a solution here
I encounter the error Cannot read properties of null (reading 'x') for origin.x,
And the strange part is, this happens after I travel a few tiles from x=0
code
import Phaser from "../lib/phaser.js";
export default class Game extends Phaser.Scene {
constructor() {
super("game1");
}
preload() {
this.load.image(
"Tileset",
"https://cdn.glitch.global/cc90578e-c3d0-47c5-bb0d-f5a81263b5b6/pixil-frame-0%20(17).png?v=1675985219390"
);
this.load.tilemapTiledJSON(
"map",
"https://cdn.glitch.global/cc90578e-c3d0-47c5-bb0d-f5a81263b5b6/Map.tmj?v=1675985261369"
);
this.load.spritesheet(
"player",
"https://cdn.glitch.global/cc90578e-c3d0-47c5-bb0d-f5a81263b5b6/pixil-frame-0%20(13).png?v=1675904194091",
{ frameWidth: 32, frameHeight: 32 }
);
}
create() {
this.gameState = {
map: "",
cursors: "",
};
this.gameState.map = this.make.tilemap({ key: "map" });
this.tiles = this.gameState.map.addTilesetImage("tileSet", "Tileset");
this.worldLayer = this.gameState.map.createLayer(
"Block Layer",
this.tiles,
0,
0
);
this.player = this.physics.add.sprite(0, 1600, "player", 1);
this.cameras.main.setBounds(
0,
0,
this.gameState.map.widthInPixels,
this.gameState.map.heightInPixels
);
this.cameras.main.startFollow(this.player);
this.gameState.cursors = this.input.keyboard.createCursorKeys();
this.physics.add.collider(this.player, this.worldLayer);
}
update() {
if (this.gameState.cursors.left.isDown) {
this.player.setVelocityX(-50);
} else if (this.gameState.cursors.right.isDown) {
this.player.setVelocityX(50);
} else if (this.gameState.cursors.up.isDown) {
this.player.setVelocityY(-50);
} else if (this.gameState.cursors.down.isDown) {
this.player.setVelocityY(-50);
} else {
this.player.setVelocityX(0);
}
this.updateMap();
}
updateMap() {
console.log(this.gameState);
var origin = this.gameState.map.getTileAtWorldXY(
this.player.x,
this.player.y
);
this.gameState.map.forEachTile(function (tile) {
var dist = Phaser.Math.Distance.Chebyshev(
origin.x,
origin.y,
tile.x,
tile.y
);
tile.setAlpha(1 - 0.1 * dist);
}, this);
}
}

Since you are moving the player with physics velocity, the player could be outside of the map, or on a position without a tile.
When map.getTileAtWorldXY is called with a position outside of the map (or some other invalid position), or there is no tile placed in that position on the layer, this function will return null, that's probably why you get this specific error.
(link to the documentation)
The easy solution would be just to exit the function, when the origin equals null. Like this:
updateMap() {
var origin = this.gameState.map.getTileAtWorldXY(
this.player.x,
this.player.y
);
if(!origin){
return;
}
...
}
Or you could have a variable like: this.gameState.lastValidPosition, that you set when the player has a valid position, and use this variable, in case of an error
updateMap() {
var origin = this.gameState.map.getTileAtWorldXY(
this.player.x,
this.player.y
);
if(!origin && !this.gameState.lastValidPosition ){
// origin is invalid and we have no valid last position
return;
} else if( !origin ) { // origin is null, w use the last valid position
origin = this.gameState.lastValidPosition;
} else { // origin is not null, so we save this position
this.gameState.lastValidPosition = origin;
}
...
}
Both solution will produce the exact same result (for most of the usecases). Which os keeping the light source at the last known/valid position.
Update:
a more easy solution could be to use the third parameter nonnull, of the function map.getTileAtWorldXY (if the issue is a missing tile), this would return a tile with index -1 instead of null.
like:
var origin = this.gameState.map.getTileAtWorldXY(
this.player.x,
this.player.y,
true
);

Related

Run a function when animation completes using Curtains.js

I'm looking to call a function right at the end of the wobble effect.
That is, at the end of the damping effect (when the wobble stops), I'd like to execute a GSAP timeline function. I'd assume this type of "onComplete" function would need to be called inside the onReady() of Curtains and perhaps by tracking the damping effect. I'm only familiar with GSAP's onComplete function, but don't know how I would implement it here. Maybe something that checks if deltas.applied is less than 0.001, then the function is called?
Below is the code snippet (without the fragment and vertex shaders). Full working code here:
CodePen
class Img {
constructor() {
const curtain = new Curtains({
container: "canvas",
watchScroll: false,
});
const params = {
vertexShader,
fragmentShader,
uniforms: {
time: {
name: "uTime",
type: "1f",
value: 0,
},
prog: {
name: "uProg",
type: "1f",
value: 0,
}
}
}
const planeElements = document.getElementsByClassName("plane")[0];
this.plane = curtain.addPlane(planeElements, params);
if (this.plane) {
this.plane
.onReady(() => {
this.introAnim();
})
.onRender(() => {
this.plane.uniforms.time.value++;
deltas.applied += (deltas.max - deltas.applied) * 0.05;
deltas.max += (0 - deltas.max) * 0.07;
this.plane.uniforms.prog.value = deltas.applied
})
}
// error handling
curtain.onError(function() {
document.body.classList.add("no-curtains");
});
}
introAnim() {
deltas.max = 6;
//console.log("complete") <-- need an onComplete type function~!
}
}
window.onload = function() {
const img = new Img();
}
What you could use is some algebra :)
First off, you should simplify your deltas.max function like so:
deltas.max += (0 - deltas.max) * 0.07;
// Simplifies to
deltas.max -= deltas.max * 0.07;
// Rewrite to
deltas.max = deltas.max - deltas.max * 0.07;
// Rewrite to
deltas.max = deltas.max * (1 - 0.07);
// Simplifies to
deltas.max *= 0.93; // Much nicer :)
That is actually pretty important to do because it makes our work of calculating the end value of our time variable and the duration of our animation significantly Easier:
// Given deltas.max *= 0.93, need to calculate end time value
// endVal = startVal * reductionFactor^n
// Rewrite as
// n = ln(endVal / startVal) / ln(reductionFactor) // for more see https://www.purplemath.com/modules/solvexpo2.htm
// n = ln(0.001 / 8) / ln(0.93)
const n = 123.84;
// Assuming 60fps normally: n / 60
const dur = 2.064;
Once we have those values all we have to do is create a linear tween animating our time to that value with that duration and update the max and prog values in the onUpdate:
gsap.to(this.plane.uniforms.time, {
value: n,
duration: dur,
ease: "none",
onUpdate: () => {
this.deltas.applied += (this.deltas.max - this.deltas.applied) * 0.05;
this.deltas.max *= 0.93;
this.plane.uniforms.prog.value = this.deltas.applied;
},
onComplete: () => console.log("complete!")
});
Then you get "complete!" when the animation finishes!
To make sure that your Curtains animations run at the proper rate even with monitors with high refresh rates (even the ones not directly animated with GSAP) it's also a good idea to turn off Curtain's autoRendering and use GSAP's ticker instead:
const curtains = new Curtains({ container: "canvas", autoRender: false });
// Use a single rAF for both GSAP and Curtains
function renderScene() {
curtains.render();
}
gsap.ticker.add(renderScene);
Altogether you get this demo.
This won't be the best answer possible but you can take some ideas and insights from it.
Open the console and see that when the animation gets completed it gets fired only once.
//Fire an onComplete event and listen for that
const event = new Event('onComplete');
class Img {
constructor() {
// Added a instance variable for encapsulation
this.animComplete = {anim1: false}
//Changed code above
const curtain = new Curtains({
container: "canvas",
watchScroll: false,
});
const params = {
vertexShader,
fragmentShader,
uniforms: {
time: {
name: "uTime",
type: "1f",
value: 0,
},
prog: {
name: "uProg",
type: "1f",
value: 0,
}
}
}
const planeElements = document.getElementsByClassName("plane")[0];
this.plane = curtain.addPlane(planeElements, params);
if (this.plane) {
this.plane
.onReady(() => {
this.introAnim();
document.addEventListener('onComplete', ()=>{
//Do damping effects here
console.log('complete')
})
})
.onRender(() => {
this.plane.uniforms.time.value++;
deltas.applied += (deltas.max - deltas.applied) * 0.05;
deltas.max += (0 - deltas.max) * 0.07;
this.plane.uniforms.prog.value = deltas.applied
if(deltas.applied<0.001 && !this.animComplete.anim1){
document.dispatchEvent(event)
this.animComplete.anim1 = true
}
})
}
// error handling
curtain.onError(function() {
document.body.classList.add("no-curtains");
});
}
introAnim() {
deltas.max = 6;
}
}
window.onload = function() {
const img = new Img();
}
I've found a solution to call a function at the end of the damping (wobble) effect, that doesn't use GSAP, but uses the Curtains onRender method. Because the uTime value goes up infinitely and the uProg value approaches 0, By tracking both the uTime and uProg values inside the Curtains onRender method we can find a point (2 thresholds) at which the damping effect has essentially completed. Not sure if this is the most efficient way, but it seems to work.
.onRender(() => {
if (this.plane.uniforms.prog.value < 0.008 && this.plane.uniforms.time.value > 50) { console.log("complete")}
})
Thanks to the Curtains docs re asynchronous-textures, I was able to better control the timing of the wobble effect with the desired result every time. That is, on computers with lower FPS, the entire damping effect takes place smoothly, with an onComplete function called at the end, as well as on comps with higher frame rates.
Although, as mentioned there is less control over the length of the effect, as we are not using GSAP to control the Utime values. Thanks #Zach! However, using a "threshold check" inside the curtains onRender this way, means the damping wobble effect is never compromised, if we were to disable the drawing at the on complete call.
By enabling the drawing at the same time the image is loaded we avoid any erratic behaviour. The following works now with hard refresh as well.
export default class Img {
constructor() {
this.deltas = {
max: 0,
applied: 0,
};
this.curtain = new Curtains({
container: "canvas",
watchScroll: false,
pixelRatio: Math.min(1.5, window.devicePixelRatio),
});
this.params = {
vertexShader,
fragmentShader,
uniforms: {
time: {
name: "uTime",
type: "1f",
value: 0,
},
prog: {
name: "uProg",
type: "1f",
value: 0,
},
},
};
this.planeElements = document.getElementsByClassName("plane")[0];
this.curtain.onError(() => document.body.classList.add("no-curtains"));
this.curtain.disableDrawing(); // disable drawing to begin with to prevent erratic timing issues
this.init();
}
init() {
this.plane = new Plane(this.curtain, this.planeElements, this.params);
this.playWobble();
}
loaded() {
return new Promise((resolve) => {
// load image and enable drawing as soon as it's ready
const asyncImgElements = document
.getElementById("async-textures-wrapper")
.getElementsByTagName("img");
// track image loading
let imagesLoaded = 0;
const imagesToLoad = asyncImgElements.length;
// load the images
this.plane.loadImages(asyncImgElements, {
// textures options
// improve texture rendering on small screens with LINEAR_MIPMAP_NEAREST minFilter
minFilter: this.curtain.gl.LINEAR_MIPMAP_NEAREST,
});
this.plane.onLoading(() => {
imagesLoaded++;
if (imagesLoaded === imagesToLoad) {
console.log("loaded");
// everything is ready, we need to render at least one frame
this.curtain.needRender();
// if window has been resized between plane creation and image loading, we need to trigger a resize
this.plane.resize();
// show our plane now
this.plane.visible = true;
this.curtain.enableDrawing();
resolve();
}
});
});
}
playWobble() {
if (this.plane) {
this.plane
.onReady(() => {
this.deltas.max = 7; // 7
})
.onRender(() => {
this.plane.uniforms.time.value++;
this.deltas.applied += (this.deltas.max - this.deltas.applied) * 0.05;
this.deltas.max += (0 - this.deltas.max) * 0.07;
this.plane.uniforms.prog.value = this.deltas.applied;
console.log(this.plane.uniforms.prog.value);
// ---- "on complete" working!! ( even on hard refresh) -----//
if (
this.plane.uniforms.prog.value < 0.001 &&
this.plane.uniforms.time.value > 50
) {
console.log("complete");
this.curtain.disableDrawing();
}
});
}
}
destroy() {
if (this.plane) {
this.curtain.disableDrawing();
this.curtain.dispose();
this.plane.remove();
}
}
}
const img = new Img();
Promise.all([img.loaded()]).then(() => {
console.log("animation started");
});

Sprite animation stuck on first frame?

Working with Phaser 3, I've preloaded a spritesheet and created a few animations...
import {Scene} from 'phaser';
class BootScene extends Scene {
constructor() {
super("scene-boot");
}
preload() {
this.load.spritesheet('px-hero', 'assets/sprites/px-hero.png', {
frameWidth: 16,
frameHeight: 16
});
// ...
}
create() {
// ...
this.anims.create({
key: 'px-hero-idle',
frames: this.anims.generateFrameNumbers('px-hero', {
start: 0,
end: 2
}),
frameRate: 10,
repeat: -1
});
this.anims.create({
key: 'px-hero-run',
frames: this.anims.generateFrameNumbers('px-hero', {
start: 3,
end: 6
}),
frameRate: 10,
repeat: -1
});
// ...
}
}
export default BootScene;
Then inside my Sprite class (which is being instantiated in another scene that the BootScene links to), I'm trying to play the animations...
import {GameObjects} from 'phaser';
const {Sprite} = GameObjects;
class PxHero extends Sprite {
constructor(config) {
super(config.scene, config.x, config.y, "px-hero");
// Add self to scene's physics
config.scene.physics.world.enable(this);
config.scene.add.existing(this);
this.scene = config.scene;
this.keys = this.scene.input.keyboard.addKeys('W,S,A,D');
this.speed = 100;
this.jumpHeight = 300;
}
preUpdate(time, delta) {
const {W, S, A, D} = this.keys;
const {speed, jumpHeight, body} = this;
const touchingGround = body.blocked.down;
if (A.isDown) {
this.body.setVelocityX(-speed);
this.setFlipX(true);
}
else if (D.isDown) {
this.body.setVelocityX(speed);
this.setFlipX(false);
}
else {
this.body.setVelocityX(0);
}
if (W.isDown && touchingGround) {
this.body.setVelocityY(-jumpHeight);
}
// Animations
if (touchingGround) {
if (body.velocity.x !== 0) {
this.anims.play('px-hero-run', true); // here
}
else {
this.anims.play('px-hero-idle', true); // and here
}
}
}
}
export default PxHero;
But for some reason they just play the first frame of the animation then get stuck there.
Has anyone encountered this before? I haven't been able to find any solutions thus far.
Per frame animations are working based on preUpdate function, it's not the best idea to do something yours in that function without calling super.preUpdate. That's first, second in place of preUpdate try to use update function, and don't forget to call super.update in it.
And third, try to do what you want without using preUpdate and update functions. If you even need to use update function, you can do that with setting listener on scene to update (Phaser.Scenes.Events.UPDATE) event. Which will make your code more clear and understandable, and you'll never harm Phaser's main functionality by mistake.
What happens in your code is the following, on every frame rendering, your game checks and decides to run an animation from start, that's why you're seeing first frames only, just because when it tries to show you next frame you're telling him to start playing animation again )
export default class PxHero extends Phaser.GameObjects.Sprite{
constructor(config) {
super(config.scene, config.x, config.y, "px-hero");
// Add self to scene's physics
// ## you've `this` here too
this.scene.add.existing(this);
this.scene.physics.world.enable(this);
this.prepare();
this.setListeners();
}
prepare(){
this.keys = this.scene.input.keyboard.addKeys('W,S,A,D');
this.speed = 100;
this.jumpHeight = 300;
}
setListeners(){
this.scene.events.on(Phaser.Scenes.Events.UPDATE, this.handleMovement, this)
}
handleMovement() {
const {W, S, A, D} = this.keys;
const {speed, jumpHeight, body} = this;
const touchingGround = body.blocked.down;
switch(true){
case A.isDown:
this.body.setVelocityX(-speed);
this.setFlipX(true);
break;
case D.isDown:
this.body.setVelocityX(speed);
this.setFlipX(false);
break;
case S.isDown:
this.body.setVelocityX(0);
break;
case W.isDown && touchingGround:
this.body.setVelocityY(-jumpHeight);
break;
}
// Animations
if (touchingGround) {
if (body.velocity.x !== 0) {
(!this.anims.isPlaying || this.anims.key !== 'px-her-run') &&
this.anims.play('px-hero-run', true); // here
}
else {
(!this.anims.isPlaying || this.anims.key !== 'px-her-idle') &&
this.anims.play('px-hero-idle', true); // and here
}
}
}
}

pts.js 'NS_ERROR_NOT_AVAILABLE: ' Error when trying to use an image for a particle

I'm wanting to load the same an image for particles in pts.js.
When I try to use a local image from my assets folder I get the error "NS_ERROR_NOT_AVAILABLE:" in the console.
I read somewhere this may be due to the image trying to be used before it has even been loaded in...
I've also tried using an external link to some other image rather than a local one and that works. So not sure what is happening with my local files.
EDIT:
I just tried this on chrome rather than firefox and I'm getting a new and more detailed error message.
"Uncaught DOMException: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The HTMLImageElement provided is in the 'broken' state." in pts.min.js:6.
Still not sure exactly what is wrong.
Pts.quickStart('#hello', 'transparent')
var world
// Loading in image to be used
var myImg = new Image()
myImg.src = '/assets/img/myImage.png'
space.add({
start: (bound, space) => {
// Create world and 100 random points
world = new World(space.innerBound, 1, 0)
let pts = Create.distributeRandom(space.innerBound, 20)
// Create particles and hit them with a random impulse
for (let i = 0, len = pts.length; i < len; i++) {
let p = new Particle(pts[i]).size(i === 0 ? 10 : 20)
p.hit(0, 0)
world.add(p)
}
world.particle(0).lock = true
},
animate: (time, ftime) => {
world.drawParticles((p, i) => {
// Image variable for the particle to be drawn as
form.image(myImg)
})
world.update(ftime)
},
action: (type, px, py) => {
if (type == 'move') {
world.particle(0).position = new Pt(px, py)
}
},
resize: (bound, evt) => {
if (world) world.bound = space.innerBound
}
})
space.bindMouse().bindTouch()
space.play()
For drawing images on canvas, the image needs to be loaded first. You can keep track of it using myImg.addEventListener( 'load', ... ).
Once it's loaded, you can use it in form.image( myImg, ... ) in Pts' animate loop.
Here's a working example based on your code above:
Pts.quickStart( "#pt", "#123" );
//// Demo code starts (anonymous function wrapper is optional) ---
(function() {
var world;
var imgReady = false;
// Loading in image to be used
var myImg = new Image()
myImg.src = 'http://icons.iconarchive.com/icons/icojoy/maneki-neko/256/cat-6-icon.png';
myImg.addEventListener('load', function() {
imgReady = true;
}, false);
space.add( {
start: (bound, space) => {
// Create world and 100 random points
world = new World( space.innerBound, 1, 0 );
let pts = Create.distributeRandom( space.innerBound, 100 );
// Create particles and hit them with a random impulse
for (let i=0, len=pts.length; i<len; i++) {
let p = new Particle( pts[i] ).size( (i===0) ? 30 : 3+Math.random()*space.size.x/50 );
p.hit( Num.randomRange(-50,50), Num.randomRange(-25, 25) );
world.add( p );
}
world.particle( 0 ).lock = true; // lock it to move it by pointer later on
},
animate: (time, ftime) => {
world.drawParticles( (p, i) => {
if (imgReady) {
console.log( p )
form.image(myImg, [p.$subtract( p.radius ), p.$add( p.radius )] );
}
});
world.update( ftime );
},
action:( type, px, py) => {
if (type == "move") {
world.particle( 0 ).position = new Pt(px, py);
}
},
resize: (bound, evt) => {
if (world) world.bound = space.innerBound;
}
});
space.bindMouse().bindTouch();
space.play();
})();

How can i get aframe box vertex coordinates?

I need to get vertex from an object (box) in an AFRAME or i need to calculate intersection between raycaster and the face of an entity.
Someone can help me? Thank you all!รง
EDIT: I added code below.
AFRAME.registerComponent("intersection-handler", {
schema: {
fps: { type: 'number', default: 15 }
},
init: function() {
this.bindMethods();
},
tick: function(){
if(new Date().getTime()-this.lastTick<(1000/this.data.fps))return;
if(this.isIntersecting){
let distance = this.calculateDistance(this.el.object3D.position, this.hittedElem.object3D.position);
this.el.emit('intersection-detected-' + this.el.id, distance );
}else{
this.el.emit('intersection-cleared-' + this.el.id);
}
this.lastTick = new Date().getTime();
},
bindMethods(){ // You could do all of this directly in your init() method, but I like to separate it.
this.onIntersection = this.onIntersection.bind(this);
this.onIntersectionClear = this.onIntersectionClear.bind(this);
},
play: function() {
this.registerEventListeners(); // It's a good practice in general to enable your event listeners here.
},
pause: function() {
this.deregisterEventListeners(); // Similarly a good practice to remove them here so that they don't stay bound while the scene isn't actually 'running'
},
registerEventListeners() {
this.el.addEventListener('raycaster-intersection', this.onIntersection);
this.el.addEventListener('raycaster-intersection-cleared', this.onIntersectionClear);
},
deregisterEventListeners() {
this.el.removeEventListener('raycaster-intersection', this.onIntersection);
this.el.removeEventListener('raycaster-intersection-cleared', this.onIntersectionClear);
},
onIntersection: function(e) {
console.log(this.el.components.raycaster.getIntersection(e.detail.els[0]))
this.isIntersecting = true;
if(e.detail.intersections[0].object){
this.hittedElem = e.detail.intersections[0].object.el;
}
},
onIntersectionClear: function(e) {
this.isIntersecting = false;
},
calculateDistance: function(myElposition, hittedElposition) {
// distance = sqrt((x2 - x1)^2 + (y2 - y1)^2) - rolloff
let rolloffFactor = 0.5;
let d = Math.sqrt(Math.pow((hittedElposition.x - myElposition.x), 2) + Math.pow((hittedElposition.y - myElposition.y), 2)) - rolloffFactor;
return d;
}
});
I can't use the raycaster-intersected event, i'm managing intersections on raycaster side not in the other entities.
no need for the vertex coordinates. The raycasters intersection.point contains a Vector3 with the intersection position.
On the other hand if you get your camera (raycasters origin) position, you get another Vector3.
From the three.js docs, you can get the distance between them with a simple a.distanceTo(b).
Fiddle here.

SVG Camera Pan - Translate keeps resetting to 0 evertime?

Well i have this SVG canvas element, i've got to the point so far that once a user clicks and drags the canvas is moved about and off-screen elements become on screen etc....
However i have this is issue in which when ever the user then goes and click and drags again then the translate co-ords reset to 0, which makes the canvas jump back to 0,0.
Here is the code that i've Got for those of you whio don't wanna use JS fiddle
Here is the JSfiddle demo - https://jsfiddle.net/2cu2jvbp/2/
edit: Got the solution - here is a JSfiddle DEMO https://jsfiddle.net/hsqnzh5w/
Any and all sugesstion will really help.
var states = '', stateOrigin;
var root = document.getElementById("svgCanvas");
var viewport = root.getElementById("viewport");
var storeCo =[];
function setAttributes(element, attribute)
{
for(var n in attribute) //rool through all attributes that have been created.
{
element.setAttributeNS(null, n, attribute[n]);
}
}
function setupEventHandlers() //self explanatory;
{
setAttributes(root, {
"onmousedown": "mouseDown(evt)", //do function
"onmouseup": "mouseUp(evt)",
"onmousemove": "mouseMove(evt)",
});
}
setupEventHandlers();
function setTranslate(element, x,y,scale) {
var m = "translate(" + x + "," + y+")"+ "scale"+"("+scale+")";
element.setAttribute("transform", m);
}
function getMousePoint(evt) { //this creates an SVG point object with the co-ords of where the mouse has been clicked.
var points = root.createSVGPoint();
points.x = evt.clientX;
points.Y = evt.clientY;
return points;
}
function mouseDown(evt)
{
var value;
if(evt.target == root || viewport)
{
states = "pan";
stateOrigin = getMousePoint(evt);
console.log(value);
}
}
function mouseMove(evt)
{
var pointsLive = getMousePoint(evt);
if(states == "pan")
{
setTranslate(viewport,pointsLive.x - stateOrigin.x, pointsLive.Y - stateOrigin.Y, 1.0); //is this re-intializing every turn?
storeCo[0] = pointsLive.x - stateOrigin.x
storeCo[1] = pointsLive.Y - stateOrigin.Y;
}
else if(states == "store")
{
setTranslate(viewport,storeCo[0],storeCo[1],1); // store the co-ords!!!
stateOrigin = pointsLive; //replaces the old stateOrigin with the new state
states = "stop";
}
}
function mouseUp(evt)
{
if(states == "pan")
{
states = "store";
if(states == "stop")
{
states ='';
}
}
}
In your mousedown function, you are not accounting for the fact that the element might already have a transform and you are just overwriting it.
You are going to need to either look for, and parse, any existing transform. Or an easier approach would be to keep a record of the old x and y offsets and when a new mousedown happens add them to the new offset.

Categories

Resources