socket.io.js path in nodejs with localhost in windows - node.js

I have installed node.js v0.10.31 and npm v1.4.3 and also installed node-uuid, socket.io and express
I am trying to create a simple chat app, but the socket.io path i referred was so confusing. my installed socket.io path is D:\program files\nodejs\node_modules\socket.io my project files in the localhost in xampp (for php)
referred from tutorials link /socket.io/socket.io.js but my link in
D:\program files\nodejs\node_modules\socket.io\node_modules\socket.io-client\socket.io.js
how can i use to include <script src="/socket.io/socket.io.js"></script> to ??
i have two files in my projectand i copied node_modules folder to project folder from nodejs
app.js
var constants = { court: { width: 600, height: 600 },
paddle: { width: 50, height: 15, delta: 3 },
ball: { radius: 10, deltaLeft: 3, deltaTop: 2, interval: 30 }
};
var state = { paddles: {},
ball: { left: 0, top: 0 },
bottomPaddle: 0,
topPaddle: 0,
leftPaddle: 0,
rightPaddle: 0
};
var serverState = { intervalId: 0,
connections: 0
};
var app = require('http').createServer(handler),
io = require('socket.io').listen(app),
fs = require('fs');
app.listen(80);
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function readfile_callback(err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
}
);
};
function calculateBallPosition() {
var left = state.ball.left + constants.ball.deltaLeft;
var top = state.ball.top + constants.ball.deltaTop;
if (left >= constants.court.width) {
left = constants.court.width;
constants.ball.deltaLeft = -constants.ball.deltaLeft;
} else if (left <= 0) {
left = 0;
constants.ball.deltaLeft = -constants.ball.deltaLeft;
}
if (top + constants.ball.radius >= constants.court.height - constants.paddle.height) {
if (state.bottomPaddle &&
left > ( (state.paddles[state.bottomPaddle]/100) * constants.court.width - constants.paddle.width / 2) &&
(left < ( (state.paddles[state.bottomPaddle]/100) * constants.court.width + constants.paddle.width / 2) ) ) {
top = constants.court.height - constants.paddle.height - constants.ball.radius;
constants.ball.deltaTop = -constants.ball.deltaTop;
} else {
//TODO: #1
left = constants.court.width / 2;
top = constants.court.height / 2;
}
} else if (top <= 0) {
top = 0;
constants.ball.deltaTop = -constants.ball.deltaTop;
}
state.ball.left = left;
state.ball.top = top;
};
io.sockets.on('connection', function (socket) {
var paddleAdded = false;
if (!state.bottomPaddle) {
state.bottomPaddle = socket.id;
} else if (!state.topPaddle) {
state.topPaddle = socket.id;
} else if (!state.leftPaddle) {
state.leftPaddle = socket.id;
} else if (!state.rightPaddle) {
state.rightPaddle = socket.id;
} else {
// placeholder for fifth player
return;
}
state.paddles[socket.id] = 50;
socket.emit('environment', { court: { width: constants.court.width,
height: constants.court.height,
},
paddle: { width: constants.paddle.width,
height: constants.paddle.height,
delta: constants.paddle.delta
},
ball: { radius: constants.ball.radius },
player: { id: socket.id }
});
if ( !serverState.intervalId ) {
serverState.intervalId = setInterval( function(){
calculateBallPosition();
}, constants.ball.interval );
}
socket.intervalId = setInterval( function(){
socket.emit('ball', { position: { left: state.ball.left, top: state.ball.top } });
socket.emit('paddles', { positions: state.paddles, sides: {bottom: state.bottomPaddle, top: state.topPaddle, left: state.leftPaddle, right: state.rightPaddle }});
}, constants.ball.interval );
socket.on('paddle', function (data) {
state.paddles[socket.id] = data.left;
});
socket.on('disconnect', function () {
serverState.connections--;
clearInterval( socket.intervalId );
delete state.paddles[socket.id];
if (state.bottomPaddle == socket.id)
state.bottomPaddle = 0;
else if (state.topPaddle == socket.id)
state.topPaddle = 0;
else if (state.leftPaddle == socket.id)
state.leftPaddle = 0;
else if (state.rightPaddle == socket.id)
state.rightPaddle = 0;
if ( serverState.connections == 0 ) {
clearInterval( serverState.intervalId );
serverState.intervalId = 0;
}
console.log('player left');
});
console.log(serverState.connections);
serverState.connections++;
});
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
.topPlayer {
-moz-transform: rotate(180deg);
}
.leftPlayer {
-moz-transform: rotate(270deg);
}
.rightPlayer {
-moz-transform: rotate(90deg);
}
</style>
</head>
<body>
<canvas id="court"></canvas>
<script src="/socket.io/socket.io.js"></script>
<script>
var constants = { court: { width: 0, height: 0, adjusted: false },
colors: { court: "brown", ball: "black", paddle: "orange" },
paddle: { width: 0, height: 0, delta: 0 },
ball: { radius: 0 },
player: { id: 0 }
};
var state = { paddles: {},
ball: { left: 0, top: 0 },
sides: {}
};
var socket = io.connect('http://localhost/pingv1'),
canvas = document.getElementById("court"),
ctx = canvas.getContext('2d');
socket.on('environment', function(data) {
constants.court.width = data.court.width;
constants.court.height = data.court.height;
constants.paddle.delta = data.paddle.delta;
constants.paddle.width = data.paddle.width;
constants.paddle.height = data.paddle.height;
constants.ball.radius = data.ball.radius;
constants.player.id = data.player.id;
});
socket.on('paddles', function(data) {
var paddles = data.positions;
// Overwrite the server's version of my own paddle position
// if I already know where I am so I don't redraw in the old spot.
if (state.paddles[constants.player.id])
paddles[constants.player.id] = state.paddles[constants.player.id];
state.paddles = paddles;
state.sides = data.sides;
if (!constants.court.adjusted) {
constants.court.adjusted = true;
if (state.sides.top == constants.player.id)
canvas.className = 'topPlayer';
else if (state.sides.left == constants.player.id)
canvas.className = 'leftPlayer';
else if (state.sides.right == constants.player.id)
canvas.className = 'rightPlayer';
}
});
socket.on('ball', function (data) {
state.ball.left = data.position.left;
state.ball.top = data.position.top;
drawCanvas();
});
var drawCanvas = function() {
canvas.width = constants.court.width;
canvas.height = constants.court.height;
ctx.fillStyle = constants.colors.court;
ctx.fillRect(0, 0, constants.court.width, constants.court.height);
ctx.fillStyle = constants.colors.paddle;
ctx.fillRect((state.paddles[state.sides.bottom] / 100 * constants.court.width) - (constants.paddle.width / 2),
constants.court.height - constants.paddle.height, constants.paddle.width, constants.paddle.height);
ctx.fillRect((state.paddles[state.sides.top] / 100 * constants.court.width) - (constants.paddle.width / 2),
0, constants.paddle.width, constants.paddle.height);
ctx.fillRect(0, (state.paddles[state.sides.left] / 100 * constants.court.height) - (constants.paddle.height / 2),
constants.paddle.height, constants.paddle.width);
ctx.fillRect(constants.court.width - constants.paddle.height,
(state.paddles[state.sides.right] / 100 * constants.court.height) - (constants.paddle.height / 2),
constants.paddle.height, constants.paddle.width);
ctx.fillStyle = constants.colors.ball;
ctx.beginPath();
ctx.arc( state.ball.left, state.ball.top, constants.ball.radius, 0, Math.PI * 2 );
ctx.fill();
};
var movePaddle = function (delta) {
var newLeft = state.paddles[constants.player.id] + delta;
if (newLeft >= 100)
newLeft = 100;
else if (newLeft <= 0)
newLeft = 0;
if (newLeft != state.paddles[constants.player.id]) {
state.paddles[constants.player.id] = newLeft;
socket.emit('paddle', {left: state.paddles[constants.player.id] });
drawCanvas();
}
};
window.addEventListener('keydown', function onKeyDown(aEvent) {
switch (aEvent.which) {
case 37: // Left
if (state.sides.top == constants.player.id || state.sides.right == constants.player.id) movePaddle(constants.paddle.delta);
else movePaddle(-constants.paddle.delta);
break;
case 39: // Right
if (state.sides.top == constants.player.id || state.sides.right == constants.player.id) movePaddle(-constants.paddle.delta);
else movePaddle(constants.paddle.delta);
break;
}
}, false);
</script>
</body>
</html>
Getting error:
GET http://localhost:3000/socket.io/?EIO=3&transport=polling&t=1423454007198-4 net::ERR_CONNECTION_REFUSED

If you set up socket.io properly with your http server (you don't show us that part of your code), then it automatically handles the request for "/socket.io/socket.io.js" and serves up the socket.io.js file to the client that actually resides elsewhere. In other words, it handles it all for you by intercepting the http request for "/socket.io/socket.io.js" and serving up the desired file from it's location in the node_modules directory that the socket.io server code came from.

Related

Draw two head arrows in fabric.js

I am new to fabric.js and don't have much experience with the browser canvas api so I appreciate all help someone will provide.
The goal to achieve is to draw with mouse arrows in 3 different modes:
With 2 heads
With one head
Without a head at all (just a plain line)
There is a very good example - but with just one "tip".
Also a more advanced topic might be: after selecting an already
created arrow, to change it (e.g. clicking on a button and change the mode from one headed arrow to two).
_render: function(ctx) {
this.callSuper('_render', ctx);
// do not render if width/height are zeros or object is not visible
if (this.width === 0 || this.height === 0 || !this.visible) return;
ctx.save();
var xDiff = this.x2 - this.x1;
var yDiff = this.y2 - this.y1;
var angle = Math.atan2(yDiff, xDiff);
ctx.translate(xDiff / 2, yDiff / 2);
ctx.rotate(angle);
ctx.beginPath();
//move 10px in front of line to start the arrow so it does not have the square line end showing in front (0,0)
ctx.moveTo(10, 0);
ctx.lineTo(-20, 15);
ctx.lineTo(-20, -15);
ctx.closePath();
ctx.fillStyle = this.stroke;
ctx.fill();
ctx.restore();
}
This particular part might be changed in place of adding another head of the arrow: <--->
Link to working JFiddle with one head: Fiddle
Thank you in advance for your help.
All the best!
Translate the context to both the end points of line, then rotate to draw the arrow heads.
DEMO
// Extended fabric line class
fabric.LineArrow = fabric.util.createClass(fabric.Line, {
type: 'lineArrow',
initialize: function(element, options) {
options || (options = {});
this.callSuper('initialize', element, options);
},
toObject: function() {
return fabric.util.object.extend(this.callSuper('toObject'));
},
_render: function(ctx) {
this.ctx = ctx;
this.callSuper('_render', ctx);
let p = this.calcLinePoints();
let xDiff = this.x2 - this.x1;
let yDiff = this.y2 - this.y1;
let angle = Math.atan2(yDiff, xDiff);
this.drawArrow(angle, p.x2, p.y2);
ctx.save();
xDiff = -this.x2 + this.x1;
yDiff = -this.y2 + this.y1;
angle = Math.atan2(yDiff, xDiff);
this.drawArrow(angle, p.x1, p.y1);
},
drawArrow: function(angle, xPos, yPos) {
this.ctx.save();
this.ctx.translate(xPos, yPos);
this.ctx.rotate(angle);
this.ctx.beginPath();
// Move 5px in front of line to start the arrow so it does not have the square line end showing in front (0,0)
this.ctx.moveTo(10, 0);
this.ctx.lineTo(-15, 15);
this.ctx.lineTo(-15, -15);
this.ctx.closePath();
this.ctx.fillStyle = this.stroke;
this.ctx.fill();
this.ctx.restore();
}
});
fabric.LineArrow.fromObject = function(object, callback) {
callback && callback(new fabric.LineArrow([object.x1, object.y1, object.x2, object.y2], object));
};
fabric.LineArrow.async = true;
var Arrow = (function() {
function Arrow(canvas) {
this.canvas = canvas;
this.className = 'Arrow';
this.isDrawing = false;
this.bindEvents();
}
Arrow.prototype.bindEvents = function() {
var inst = this;
inst.canvas.on('mouse:down', function(o) {
inst.onMouseDown(o);
});
inst.canvas.on('mouse:move', function(o) {
inst.onMouseMove(o);
});
inst.canvas.on('mouse:up', function(o) {
inst.onMouseUp(o);
});
inst.canvas.on('object:moving', function(o) {
inst.disable();
})
}
Arrow.prototype.onMouseUp = function(o) {
var inst = this;
this.line.set({
dirty: true,
objectCaching: true
});
inst.canvas.renderAll();
inst.disable();
};
Arrow.prototype.onMouseMove = function(o) {
var inst = this;
if (!inst.isEnable()) {
return;
}
var pointer = inst.canvas.getPointer(o.e);
var activeObj = inst.canvas.getActiveObject();
activeObj.set({
x2: pointer.x,
y2: pointer.y
});
activeObj.setCoords();
inst.canvas.renderAll();
};
Arrow.prototype.onMouseDown = function(o) {
var inst = this;
inst.enable();
var pointer = inst.canvas.getPointer(o.e);
var points = [pointer.x, pointer.y, pointer.x, pointer.y];
this.line = new fabric.LineArrow(points, {
strokeWidth: 5,
fill: 'red',
stroke: 'red',
originX: 'center',
originY: 'center',
hasBorders: false,
hasControls: false,
objectCaching: false,
perPixelTargetFind: true
});
inst.canvas.add(this.line).setActiveObject(this.line);
};
Arrow.prototype.isEnable = function() {
return this.isDrawing;
}
Arrow.prototype.enable = function() {
this.isDrawing = true;
}
Arrow.prototype.disable = function() {
this.isDrawing = false;
}
return Arrow;
}());
var canvas = new fabric.Canvas('canvas', {
selection: false
});
var arrow = new Arrow(canvas);
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.17/fabric.min.js"></script>
Please draw arrow here
<div id="canvasContainer">
<canvas id="canvas" width="400" height="400" style="border: solid 1px"></canvas>
</div>
In order to do simple line, one head or two heads for an arrow you'll need to path a custom option. I updated #Durga code using custom option. I have used and array: heads: [1,1]. Available options for the heads can be 0 or 1. 0 - no head, 1 - with head. So in that case you can control which head to display: left, right, both or nothing:
// Extended fabric line class
fabric.LineArrow = fabric.util.createClass(fabric.Line, {
type: 'lineArrow',
initialize: function(element, options) {
options || (options = {});
this.callSuper('initialize', element, options);
},
toObject: function() {
return fabric.util.object.extend(this.callSuper('toObject'));
},
_render: function(ctx) {
this.ctx = ctx;
this.callSuper('_render', ctx);
let p = this.calcLinePoints();
let xDiff = this.x2 - this.x1;
let yDiff = this.y2 - this.y1;
let angle = Math.atan2(yDiff, xDiff);
this.drawArrow(angle, p.x2, p.y2, this.heads[0]);
ctx.save();
xDiff = -this.x2 + this.x1;
yDiff = -this.y2 + this.y1;
angle = Math.atan2(yDiff, xDiff);
this.drawArrow(angle, p.x1, p.y1,this.heads[1]);
},
drawArrow: function(angle, xPos, yPos, head) {
this.ctx.save();
if (head) {
this.ctx.translate(xPos, yPos);
this.ctx.rotate(angle);
this.ctx.beginPath();
// Move 5px in front of line to start the arrow so it does not have the square line end showing in front (0,0)
this.ctx.moveTo(10, 0);
this.ctx.lineTo(-15, 15);
this.ctx.lineTo(-15, -15);
this.ctx.closePath();
}
this.ctx.fillStyle = this.stroke;
this.ctx.fill();
this.ctx.restore();
}
});
fabric.LineArrow.fromObject = function(object, callback) {
callback && callback(new fabric.LineArrow([object.x1, object.y1, object.x2, object.y2], object));
};
fabric.LineArrow.async = true;
var Arrow = (function() {
function Arrow(canvas) {
this.canvas = canvas;
this.className = 'Arrow';
this.isDrawing = false;
this.bindEvents();
}
Arrow.prototype.bindEvents = function() {
var inst = this;
inst.canvas.on('mouse:down', function(o) {
inst.onMouseDown(o);
});
inst.canvas.on('mouse:move', function(o) {
inst.onMouseMove(o);
});
inst.canvas.on('mouse:up', function(o) {
inst.onMouseUp(o);
});
inst.canvas.on('object:moving', function(o) {
inst.disable();
})
}
Arrow.prototype.onMouseUp = function(o) {
var inst = this;
this.line.set({
dirty: true,
objectCaching: true
});
inst.canvas.renderAll();
inst.disable();
};
Arrow.prototype.onMouseMove = function(o) {
var inst = this;
if (!inst.isEnable()) {
return;
}
var pointer = inst.canvas.getPointer(o.e);
var activeObj = inst.canvas.getActiveObject();
activeObj.set({
x2: pointer.x,
y2: pointer.y
});
activeObj.setCoords();
inst.canvas.renderAll();
};
Arrow.prototype.onMouseDown = function(o) {
var inst = this;
inst.enable();
var pointer = inst.canvas.getPointer(o.e);
var points = [pointer.x, pointer.y, pointer.x, pointer.y];
this.line = new fabric.LineArrow(points, {
strokeWidth: 5,
fill: 'red',
stroke: 'red',
originX: 'center',
originY: 'center',
hasBorders: false,
hasControls: false,
objectCaching: false,
perPixelTargetFind: true,
heads: [1, 0]
});
inst.canvas.add(this.line).setActiveObject(this.line);
};
Arrow.prototype.isEnable = function() {
return this.isDrawing;
}
Arrow.prototype.enable = function() {
this.isDrawing = true;
}
Arrow.prototype.disable = function() {
this.isDrawing = false;
}
return Arrow;
}());
var canvas = new fabric.Canvas('canvas', {
selection: false
});
var arrow = new Arrow(canvas);
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.17/fabric.min.js"></script>
Please draw arrow here
<div id="canvasContainer">
<canvas id="canvas" width="400" height="400" style="border: solid 1px"></canvas>
</div>https://stackoverflow.com/questions/53114152/draw-two-head-arrows-in-fabric-js#
P.S. all credits for Durga. I just did small modifications to his code.
UPDATE to use dynamic stroke width
To use dynamic stroke width, drawArrow must take strokeWidth into drawing a triangle, so it will be the following changes inside drawArrow function:
this.ctx.moveTo(this.strokeWidth, 0);
this.ctx.lineTo(-this.strokeWidth*2, this.strokeWidth*2);
this.ctx.lineTo(-this.strokeWidth*2, -this.strokeWidth*2);
Final code is here:
// Extended fabric line class
fabric.LineArrow = fabric.util.createClass(fabric.Line, {
type: 'lineArrow',
initialize: function(element, options) {
options || (options = {});
this.callSuper('initialize', element, options);
},
toObject: function() {
return fabric.util.object.extend(this.callSuper('toObject'));
},
_render: function(ctx) {
this.ctx = ctx;
this.callSuper('_render', ctx);
let p = this.calcLinePoints();
let xDiff = this.x2 - this.x1;
let yDiff = this.y2 - this.y1;
let angle = Math.atan2(yDiff, xDiff);
this.drawArrow(angle, p.x2, p.y2, this.heads[0]);
ctx.save();
xDiff = -this.x2 + this.x1;
yDiff = -this.y2 + this.y1;
angle = Math.atan2(yDiff, xDiff);
this.drawArrow(angle, p.x1, p.y1,this.heads[1]);
},
drawArrow: function(angle, xPos, yPos, head) {
this.ctx.save();
if (head) {
this.ctx.translate(xPos, yPos);
this.ctx.rotate(angle);
this.ctx.beginPath();
this.ctx.moveTo(this.strokeWidth, 0);
this.ctx.lineTo(-this.strokeWidth*2, this.strokeWidth*2);
this.ctx.lineTo(-this.strokeWidth*2, -this.strokeWidth*2);
this.ctx.closePath();
}
this.ctx.fillStyle = this.stroke;
this.ctx.fill();
this.ctx.restore();
}
});
fabric.LineArrow.fromObject = function(object, callback) {
callback && callback(new fabric.LineArrow([object.x1, object.y1, object.x2, object.y2], object));
};
fabric.LineArrow.async = true;
var Arrow = (function() {
function Arrow(canvas) {
this.canvas = canvas;
this.className = 'Arrow';
this.isDrawing = false;
this.bindEvents();
}
Arrow.prototype.bindEvents = function() {
var inst = this;
inst.canvas.on('mouse:down', function(o) {
inst.onMouseDown(o);
});
inst.canvas.on('mouse:move', function(o) {
inst.onMouseMove(o);
});
inst.canvas.on('mouse:up', function(o) {
inst.onMouseUp(o);
});
inst.canvas.on('object:moving', function(o) {
inst.disable();
})
}
Arrow.prototype.onMouseUp = function(o) {
var inst = this;
this.line.set({
dirty: true,
objectCaching: true
});
inst.canvas.renderAll();
inst.disable();
};
Arrow.prototype.onMouseMove = function(o) {
var inst = this;
if (!inst.isEnable()) {
return;
}
var pointer = inst.canvas.getPointer(o.e);
var activeObj = inst.canvas.getActiveObject();
activeObj.set({
x2: pointer.x,
y2: pointer.y
});
activeObj.setCoords();
inst.canvas.renderAll();
};
Arrow.prototype.onMouseDown = function(o) {
var inst = this;
inst.enable();
var pointer = inst.canvas.getPointer(o.e);
var points = [pointer.x, pointer.y, pointer.x, pointer.y];
this.line = new fabric.LineArrow(points, {
strokeWidth: 20,
fill: 'red',
stroke: 'red',
originX: 'center',
originY: 'center',
hasBorders: false,
hasControls: false,
objectCaching: false,
perPixelTargetFind: true,
heads: [1, 0]
});
inst.canvas.add(this.line).setActiveObject(this.line);
};
Arrow.prototype.isEnable = function() {
return this.isDrawing;
}
Arrow.prototype.enable = function() {
this.isDrawing = true;
}
Arrow.prototype.disable = function() {
this.isDrawing = false;
}
return Arrow;
}());
var canvas = new fabric.Canvas('canvas', {
selection: false
});
var arrow = new Arrow(canvas);
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.17/fabric.min.js"></script>
Please draw arrow here
<div id="canvasContainer">
<canvas id="canvas" width="800" height="800" style="border: solid 1px"></canvas>
</div>

How to solve after panning object will no longer be selectable in fabric.js?

Below is the reproduction of the problem: jsfiddle. Code is mostly taken from official tutorial.
var canvas = new fabric.Canvas('c');
canvas.setBackgroundImage('//www.datashinobi.com/data/person/Charlotte%20Casiraghi/0622cdb484c35923528b1537fd1970785b00241f367ff466fc36c414a50ca973.jpg')
canvas.uniScaleTransform = true
canvas.on('mouse:down', function (opt) {
var evt = opt.e;
if (evt.ctrlKey == true) {
canvas.selection = false;
canvas.forEachObject(function(o) {
o.selectable = false;
});
this.isDragging = true;
this.selection = false;
this.lastPosX = evt.clientX;
this.lastPosY = evt.clientY;
}
});
canvas.on('mouse:move', function (opt) {
if (this.isDragging) {
var e = opt.e;
this.viewportTransform[4] += e.clientX - this.lastPosX;
this.viewportTransform[5] += e.clientY - this.lastPosY;
this.requestRenderAll();
this.lastPosX = e.clientX;
this.lastPosY = e.clientY;
}
});
canvas.on('mouse:up', function (opt) {
this.isDragging = false;
this.selection = true;
canvas.selection = true;
canvas.forEachObject(function(o) {
o.selectable = true;
});
});
canvas.on('mouse:wheel', function (opt) {
var delta = opt.e.deltaY;
var pointer = canvas.getPointer(opt.e);
var zoom = canvas.getZoom();
zoom = zoom - delta * 0.01;
if (zoom > 9) {
zoom = 9;
}
if (zoom < 1) {
zoom = 1;
}
canvas.zoomToPoint({x: opt.e.offsetX, y: opt.e.offsetY}, zoom);
opt.e.preventDefault();
opt.e.stopPropagation();
});
var rect = new fabric.Rect({
left: 100,
top: 100,
fill: 'red',
width: 100,
height: 100,
opacity: 0.4,
hasRotatingPoint: false,
hasBorders: false,
})
canvas.add(rect);
<script src="//cdnjs.cloudflare.com/ajax/libs/fabric.js/2.2.1/fabric.min.js"></script>
<canvas id="c" width="1000" height="1000"></canvas>
Press ctrl to pan. Try a large pan(but object still within view) and select the object. And try a few times and you will face the problem I mention, which is that the object is no longer selectable. However, if you press around you may be able to select it, which is weird and feels buggy.
How can I solve this problem?
All you need is object.setCoords() to set all the coordinate of corners inside mouse:up callback.
DEMO
var canvas = new fabric.Canvas('c');
canvas.setBackgroundImage('//www.datashinobi.com/data/person/Charlotte%20Casiraghi/0622cdb484c35923528b1537fd1970785b00241f367ff466fc36c414a50ca973.jpg', canvas.renderAll.bind(canvas))
canvas.uniScaleTransform = true
canvas.on('mouse:down', function(opt) {
var evt = opt.e;
if (evt.ctrlKey == true) {
canvas.selection = false;
canvas.discardActiveObject();
canvas._currentTransform = null; canvas.forEachObject(function(o) {
o.selectable = false;
});
this.isDragging = true;
this.selection = false;
this.lastPosX = evt.clientX;
this.lastPosY = evt.clientY;
}
});
canvas.on('mouse:move', function(opt) {
if (this.isDragging) {
var e = opt.e;
this.viewportTransform[4] += e.clientX - this.lastPosX;
this.viewportTransform[5] += e.clientY - this.lastPosY;
this.requestRenderAll();
this.lastPosX = e.clientX;
this.lastPosY = e.clientY;
}
});
canvas.on('mouse:up', function(opt) {
this.isDragging = false;
this.selection = true;
canvas.selection = true;
canvas.forEachObject(function(o) {
o.selectable = true;
o.setCoords();
});
});
canvas.on('mouse:wheel', function(opt) {
var delta = opt.e.deltaY;
var pointer = canvas.getPointer(opt.e);
var zoom = canvas.getZoom();
zoom = zoom - delta * 0.01;
if (zoom > 9) {
zoom = 9;
}
if (zoom < 1) {
zoom = 1;
}
canvas.zoomToPoint({
x: opt.e.offsetX,
y: opt.e.offsetY
}, zoom);
opt.e.preventDefault();
opt.e.stopPropagation();
});
var rect = new fabric.Rect({
left: 100,
top: 100,
fill: 'red',
width: 100,
height: 100,
opacity: 0.4,
hasRotatingPoint: false,
hasBorders: false,
})
canvas.add(rect);
<script src="//cdnjs.cloudflare.com/ajax/libs/fabric.js/2.2.1/fabric.min.js"></script>
<canvas id="c" width="1000" height="1000"></canvas>

How to rotate sprite image in 360 degree view in fabric js

But the problem is iam not able to rotate the sprite image based on user interaction.for eg: when the user moves the mouse on right the frame on right side should moved and when the user moves on left the left side of the frames should me moved iam not able to implement this in fabric js. What i have done is just rotating the sprite image onmouse move.Expected output i want is like this :https://codyhouse.co/demo/360-degrees-product-viewer/index.html
var URL = 'https://codyhouse.co/demo/360-degrees-product-viewer/img/alfa.png';
var canvas = new fabric.Canvas('canvas');
var positions = {
topSteps: 1,
leftSteps: 16
};
var y = 0;
var x = 0;
var topStep;
var leftStep;
canWalk(URL, positions);
function canWalk(URL, positions) {
var myImage = new Image();
myImage.src = URL;
//var mDown = false;
//onloadevent
myImage.onload = function () {
topStep = myImage.naturalHeight / positions.topSteps;
leftStep = myImage.naturalWidth / positions.leftSteps;
var docCanvas = document.getElementById('canvas');
docCanvas.height = topStep;
docCanvas.width = leftStep;
fabricImageFromURL(x, y);
};
}
//mouseevents
canvas.on('mouse:out', function (event) {
console.log("mouseout")
/* x=0;
y=0;
fabricImageFromURL(x,y);*/
});
canvas.on('mouse:move', function (event) {
resetvalue();
setTimeout(function () {
console.log('value of x in start', x)
console.log('positions.leftSteps', positions.leftSteps)
if (x == positions.leftSteps) {
y = 1;
fabricImageFromURL(-y * topStep, -x * leftStep)
}
else {
fabricImageFromURL(-y * topStep, -x * leftStep)
if (x < positions.leftSteps) {
x++;
}
}
}, 50);
});
function resetvalue() {
if (x == positions.leftSteps) {
x = 0;
y = 0;
console.log("x and y value reset to0")
}
}
function fabricImageFromURL(top, left) {
console.log('fabricImageFromURL value', top, left);
fabric.Image.fromURL(URL, function (oImg) {
oImg.set('left', left).set('top', top);
oImg.hasControls = false;
oImg.hasBorders = false;
oImg.selectable = false;
canvas.add(oImg);
canvas.renderAll();
}, { "left": 0, "top": 0, "scaleX": 1, "scaleY": 1 });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.21/fabric.js"></script>
<canvas id="canvas"></canvas>
As we are not changing top value, no need to set top value all the time, just set left value for the image. pixelToSkip is the difference between mousemove pixel to call the function, if mouse move difference is less than that , then it wont call.
var URL = 'https://codyhouse.co/demo/360-degrees-product-viewer/img/alfa.png';
var canvas = new fabric.Canvas('canvas', {
selection: false
}),
imgObject;
var positions = {
topSteps: 1,
leftSteps: 16
};
var y = 0;
var x = 0;
var topStep;
var leftStep;
var isMouseDown = false;
var imgObject, pixelToSkip = 10;
var clickedPointer, currPointer, diff;
canWalk(URL, positions);
function canWalk(URL, positions) {
var myImage = new Image();
myImage.src = URL;
//var mDown = false;
//onloadevent
myImage.onload = function() {
topStep = myImage.naturalHeight / positions.topSteps;
leftStep = myImage.naturalWidth / positions.leftSteps;
canvas.setDimensions({
height : topStep,
width : leftStep
})
fabricImageFromURL(x, y);
};
}
//mouseevents
canvas.on('mouse:down', function(event) {
isMouseDown = true;
prevPointer = canvas.getPointer(event.e);
})
canvas.on('mouse:out', function(event) {
//console.log("mouseout")
/* x=0;
y=0;
fabricImageFromURL(x,y);*/
});
canvas.on('mouse:move', function(event) {
if (!isMouseDown) return;
currPointer = canvas.getPointer(event.e);
diff = currPointer.x - prevPointer.x;
if (diff < -pixelToSkip) {
if (x == positions.leftSteps) {
x = 0;
}
fabricImageFromURL(-x * leftStep)
x++;
prevPointer = currPointer;
} else if(diff > pixelToSkip){
if (x == 0) {
x = positions.leftSteps;
}
x--;
fabricImageFromURL(-x * leftStep)
prevPointer = currPointer;
}
});
canvas.on('mouse:up', function(event) {
isMouseDown = false;
})
function fabricImageFromURL(left) {
if (!imgObject) return
imgObject.set('left', left);
canvas.renderAll();
}
fabric.Image.fromURL(URL, function(oImg) {
imgObject = oImg;
oImg.set({
left: 0,
top: 0,
hasControls: false,
hasBorders: false,
selectable: false
});
canvas.add(oImg);
canvas.renderAll();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.21/fabric.js"></script>
<canvas id="canvas"></canvas>

Fabricjs - How to move the selected object by keyboard

i want to move the selected object by keyboard,because it can be moved more accurately,I don't know how to do it.
Here is my simple implementation of moving selected object/group using left/up/right/down keys:
https://jsfiddle.net/milanhlinak/4fofjzvm/
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="lib/jquery-3.1.1.min.js"></script>
<script type="text/javascript" src="lib/fabric.min.js"></script>
</head>
<body>
<canvas id="canvas" style="border: 1px solid #cccccc"></canvas>
<script>
const STEP = 10;
var Direction = {
LEFT: 0,
UP: 1,
RIGHT: 2,
DOWN: 3
};
var canvas = new fabric.Canvas('canvas', {
width: 500,
height: 500,
});
canvas.add(new fabric.Rect({
left: 100,
top: 100,
width: 50,
height: 50,
fill: '#faa'
}));
canvas.add(new fabric.Rect({
left: 300,
top: 300,
width: 50,
height: 50,
fill: '#afa'
}));
fabric.util.addListener(document.body, 'keydown', function (options) {
if (options.repeat) {
return;
}
var key = options.which || options.keyCode; // key detection
if (key === 37) { // handle Left key
moveSelected(Direction.LEFT);
} else if (key === 38) { // handle Up key
moveSelected(Direction.UP);
} else if (key === 39) { // handle Right key
moveSelected(Direction.RIGHT);
} else if (key === 40) { // handle Down key
moveSelected(Direction.DOWN);
}
});
function moveSelected(direction) {
var activeObject = canvas.getActiveObject();
var activeGroup = canvas.getActiveGroup();
if (activeObject) {
switch (direction) {
case Direction.LEFT:
activeObject.setLeft(activeObject.getLeft() - STEP);
break;
case Direction.UP:
activeObject.setTop(activeObject.getTop() - STEP);
break;
case Direction.RIGHT:
activeObject.setLeft(activeObject.getLeft() + STEP);
break;
case Direction.DOWN:
activeObject.setTop(activeObject.getTop() + STEP);
break;
}
activeObject.setCoords();
canvas.renderAll();
console.log('selected objects was moved');
} else if (activeGroup) {
switch (direction) {
case Direction.LEFT:
activeGroup.setLeft(activeGroup.getLeft() - STEP);
break;
case Direction.UP:
activeGroup.setTop(activeGroup.getTop() - STEP);
break;
case Direction.RIGHT:
activeGroup.setLeft(activeGroup.getLeft() + STEP);
break;
case Direction.DOWN:
activeGroup.setTop(activeGroup.getTop() + STEP);
break;
}
activeGroup.setCoords();
canvas.renderAll();
console.log('selected group was moved');
} else {
console.log('no object selected');
}
}
</script>
</body>
</html>
Here is a simple function that'll do the work:
<canvas id="canvas" onkeydown="onKeyDown" tabindex="0"></canvas>
function onKeyDown(event) {
const STEP = 1;
// prevent scrolling
event.preventDefault();
let keyCode = event.keyCode || event.which;
let activeGroup = this.canvas.getActiveObjects();
if (Array.isArray(activeGroup)) {
activeGroup.forEach(obj => {
switch (keyCode) {
case 37: // left
obj.left = obj.left - STEP;
break;
case 38: // up
obj.top = obj.top - STEP;
break;
case 39: // right
obj.left = obj.left + STEP;
break;
case 40: // down
obj.top = obj.top + STEP;
break;
}
obj.setCoords();
});
this.canvas.renderAll();
}
}

I am trying to export rallygrid data in excel file, but getting only headers not values

I am trying to export rallygrid data in excel file, but getting only headers not values.
Below is my code which I wrote to generate grid and export button
From here [https://github.com/andreano/TaskDelta/blob/master/App.js], I stole the export code
prepareChart: function(iteration_data) {
this.converted_values = [];
this.accept_values = [];
this.commit_values = [];
parents = [];
rootParent = this.getContext().getProject().Name;
sortedArray = [];
var project_hash = {}; // project_by_name, with children
Ext.Array.each(iteration_data, function(iteration){
if ((iteration.ProjectName != rootParent && iteration.ChildCount > 0) || iteration.ParentName == rootParent) {
parents.push(iteration.ProjectName);
}
// make a place for me
if ( ! project_hash[iteration.ProjectName] ) { project_hash[iteration.ProjectName] = []; }
// make a place for my parent so it can know children
if ( iteration.ParentName ) {
if ( ! project_hash[iteration.ParentName]) { project_hash[iteration.ParentName] = []; }
project_hash[iteration.ParentName] = Ext.Array.merge( project_hash[iteration.ParentName], iteration.ProjectName);
}
}, this);
// build order this way:
//console.log("Current: ", this.getContext().getProject().Name );
// order the array by parents to children to grandchildren
sortedArray = this._getTreeArray( this.getContext().getProject().Name , project_hash);
parents = Ext.Array.unique(parents);
sortedData = [];
Ext.Array.each(sortedArray, function(name){
Ext.Array.each(iteration_data, function(ite){
if(ite.ProjectName == name) {
sortedData.push(ite);
};
});
});
Ext.Array.each(iteration_data, function(iteration){
if (iteration.ProjectName == rootParent) {
sortedData.push(iteration);
}
}, this);
iteration_data = sortedData;
sprints = [];
teams = [];
this.ratio = {};
for ( var i=0; i<iteration_data.length; i++ ) {
commit_accept_ratio = 0;
var data_point = iteration_data[i];
this.commit_values.push( data_point.Commit );
this.accept_values.push( data_point.Accept );
if ( data_point.Commit > data_point.Accept ) {
this.converted_values.push( data_point.Commit - data_point.Accept );
} else {
this.converted_values.push( 0 );
}
if (data_point.Commit != 0) {
commit_accept_ratio = (data_point.Accept / data_point.Commit ) * 100;
} else {
commit_accept_ratio = 0;
};
sprints.push(iteration_data[i].Name);
teams.push(iteration_data[i].ProjectName);
teams.push(rootParent);
this.ratio[data_point.ObjectID] = commit_accept_ratio;
}
this.sprints = Ext.Array.unique(sprints).sort();
this.teams = Ext.Array.unique(teams);
removable_teams = [];
for ( var i=0; i<this.teams.length; i++ ) {
team_name = null;
var count = 0;
Ext.Array.each(iteration_data, function(data) {
if (this.teams[i] == data.ProjectName && data.Commit == 0 || null || undefined && data.Accept == 0 || null || undefined) {
count += 1;
team_name = data.ProjectName;
}
}, this);
if (count == this.sprints.length) {
removable_teams.push(team_name);
}
}
removable_teams = Ext.Array.unique(removable_teams);
records = [];
recordHash = {};
summaryHash = {};
Ext.Array.each(iteration_data, function(iter) {
if (!recordHash[iter.ProjectName]) {
recordHash[iter.ProjectName] = {
Team: iter.ProjectName,
Name: '4 Sprint Summary',
Commit: [],
Accept: [],
Perc: [],
Summary: 0
};
}
if (!Ext.Array.contains(removable_teams, iter.ProjectName)) {
recordHash[iter.ProjectName]["Commit-" + iter.Name] = iter.Commit;
recordHash[iter.ProjectName]["Accept-" + iter.Name] = iter.Accept;
recordHash[iter.ProjectName]["Perc-" + iter.Name] = this.ratio[iter.ObjectID];
}
}, this);
var summaryArray = Ext.Array.slice( this.sprints, (this.sprints.length - 4))
var iterated_data = [];
Ext.Array.each(summaryArray, function(summ){
Ext.Array.each(iteration_data, function(team) {
if( summ == team.Name){
iterated_data.push(team);
}
});
});
Ext.Array.each(iteration_data, function(summ){
Ext.Array.each(iterated_data, function(team) {
if (!summaryHash[team.ProjectName]) {
summaryHash[team.ProjectName] = {
Commit: 0,
Accept: 0,
Total: 0
};
};
if (!Ext.Array.contains(removable_teams, team.ProjectName)) {
if( summ.ProjectName == team.ProjectName && summ.Name == team.Name) {
summaryHash[team.ProjectName]["Commit"] += summ.Commit;
summaryHash[team.ProjectName]["Accept"] += summ.Accept;
if (summaryHash[team.ProjectName]["Commit"] != 0) {
summaryHash[team.ProjectName]["Total"] = (summaryHash[team.ProjectName]["Accept"] / summaryHash[team.ProjectName]["Commit"] ) * 100;
} else {
summaryHash[team.ProjectName]["Total"] = 0;
};
};
}
});
}, this);
Ext.Object.each(recordHash, function(key, value) {
if (summaryHash[key]) {
value["Summary"] = summaryHash[key].Total;
records.push(value);
}
});
var cfgsValues = [];
cfgsValues.push({text: 'Team', style:"background-color: #D2EBC8", dataIndex: 'Team', width: 170, renderer: function(value, meta_data, record, row, col) {
if (Ext.Array.contains(parents, value)) {
meta_data.style = "background-color: #FFF09E";
return Ext.String.format("<div style='font-weight:bold;text-align:center'>{0}</div>", value);
} else if (rootParent == value){
meta_data.style = "background-color: #CC6699";
return Ext.String.format("<div style='font-weight:bold;text-align:center'>{0}</div>", value);
} else {
return value;
};
}});
cfgsValues.push({text: '4 Sprint Summary', style:"background-color: #D2EBC8", width: 70, dataIndex: 'Summary', renderer: function(value, meta_data, record) {
var color = null;
if (value >= 80 && value <= 120) {
color = "#00AF4F";
}
else if (value >= 60 && value <= 80) {
color = "#FBFE08";
}
else if (value <= 60) {
color = "#FC0002";
}
else if (value >= 120) {
color = "#98CCFB";
};
meta_data.style = "background-color: "+color+"";
return Ext.Number.toFixed(value, 0)+"%";
}});
Ext.Array.each(this.sprints, function(sprint) {
cfgsValues.push(
{text: sprint, style:'background-color:#D2EBC8;text-align:center;font-weight:bold', defaults: {enableColumnHide:false}, columns:[
{text: "Commit", dataIndex: 'Commit-' + sprint, width: 50, renderer: function(value, meta_data, record) {
if( value ) {
return value;
} else {
return "NA";
}
}},
{text: "Accept", dataIndex: 'Accept-' + sprint, width: 60, renderer: function(value, meta_data, record) {
if( value) {
return value;
} else {
return "NA";
}
}},
{text: "%", dataIndex: 'Perc-'+ sprint, width: 50, renderer: function(value, meta_data, record) {
var color = null;
if (value >= 80 && value <= 120) {
color = "#00AF4F";
}
else if (value >= 60 && value <= 80) {
color = "#FBFE08";
}
else if (value <= 60) {
color = "#FC0002";
}
else if (value >= 120) {
color = "#98CCFB";
}
meta_data.style = "background-color: "+color+"";
if (value) {
return Ext.Number.toFixed(value, 0)+"%";
} else {
return "NA";
};
}}
]}
);
});
var chart = Ext.getCmp('mychart');
if (chart) {
chart.destroy();
};
Ext.Array.each(this.sprints, function(sprint) {
Ext.Array.each(records, function(record) {
if (record["Accept-" + sprint] == undefined) {
record["Accept-" + sprint] = undefined;
}
if (record["Commit-" + sprint] == undefined) {
record["Commit-" + sprint] = undefined;
}
if (record["Perc-" + sprint] == undefined) {
record["Perc-" + sprint] = undefined;
}
});
});
this.add({
xtype: 'rallygrid',
id: 'mychart',
store: Ext.create('Rally.data.custom.Store', {
data: records,
pageSize: 100
}),
//viewConfig: {
//stripeRows: false
//},
columnCfgs: cfgsValues,
//columnLines: true
});
this.globalStore = Ext.getCmp('mychart');
console.log("this.globalStore", this.globalStore);
this.down('#grid_box').add(this.globalStore);
//this.setLoading(false);
},
_addPrintButton: function() {
var me = this;
this.down('#print_button_box').add( {
xtype: 'rallybutton',
itemId: 'print_button',
text: 'Export to Excel',
disabled: false,
margin: '20 10 10 0',
region: "right",
handler: function() {
me._onClickExport();
}
});
},
_onClickExport: function () { //using this function to export to csv
var that = this;
if (this.down('#grid_box')){
//Ext.getBody().mask('Exporting Tasks...');
//console.log('inside export');
setTimeout(function () {
var template = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-' +
'microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head>' +
'<!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>' +
'{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet>' +
'</x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table>{table}' +
'</table></body></html>';
var base64 = function (s) {
return window.btoa(unescape(encodeURIComponent(s)));
};
var format = function (s, c) {
return s.replace(/{(\w+)}/g, function (m, p) {
return c[p];
});
};
var table = that.getComponent('grid_box');
//console.log("Exporting table ",table);
var excel_data = '<tr>';
Ext.Array.each(table.getEl().dom.outerHTML.match(/<span .*?x-column-header-text.*?>.*?<\/span>/gm), function (column_header_span) {
excel_data += (column_header_span.replace(/span/g, 'td'));
});
excel_data += '</tr>';
Ext.Array.each(table.getEl().dom.outerHTML.match(/<tr class="x-grid-row.*?<\/tr>/gm), function (line) {
excel_data += line.replace(/[^\011\012\015\040-\177]/g, '>>');
});
//console.log("Excel data ",excel_data);
var ctx = {worksheet: name || 'Worksheet', table: excel_data};
window.location.href = 'data:application/vnd.ms-excel;base64,' + base64(format(template, ctx));
Ext.getBody().unmask();
}, 500);
}else{
console.log("grid_box does not exist");
}
}
There is an example in new AppSDK2 documentation of exporting to CSV.
I also have an example of exporting to CSV in this github repo.

Resources