Related
I'm trying to make a function that exactly does this direction drop in the rectangle, could anyone help me?
I do not know how I can break the rectangle from the horizontal direction to the vertical.
I have no idea how I'm going to break the rectangle and add a new new rectangle.
Maybe I have to use only separate lines?
How can I make the drawing the same?
If anyone can help me! I am desperate!
IMAGE example LINK HERE !!!!
<script>
$(document).ready(function () {
var canvas = new fabric.Canvas('canvas');
canvas.selection = false;
var rect, isDown, origX, origY, freeDrawing = true, textVal, activeObj;
var isRectActive = true;
var rectangle = document.getElementById('rect');
var obj_selecionado = false;
var started = false;
var prvX = -300;
var prvY = -300;
rectangle.addEventListener('click', function () {
isRectActive = !isRectActive;
});
canvas.on('mouse:down', function (o) {
if (freeDrawing) {
isDown = true;
var pointer = canvas.getPointer(o.e);
origX = pointer.x;
origY = pointer.y;
prvX = pointer.x;
prvY = pointer.y;
started = true;
if (isRectActive) {
rect = new fabric.Rect({
left: origX,
top: origY,
width: pointer.x - origX,
height: pointer.y - origY,
fill: '',
stroke: 'gray',
type: 'rect',
uuid: generateUUID(),
strokeWidth: 1
});
canvas.add(rect);
activeObj = rect;
}
}
});
canvas.on('mouse:move', function (o) {
if (isDown && freeDrawing) {
var pointer = canvas.getPointer(o.e);
if (!started) return;
if (isRectActive) {
//HERE ADD SOMETHING TO BREAK RECTANGLE
var dx = pointer.x - prvX;
var dy = pointer.y - prvY;
if (Math.abs(dx) > Math.abs(dy)) {
rect.set({ width: dx });
rect.set({ height: 120 });
} else {
rect.set({ width: 120 });
rect.set({ height: dy });
}
}
canvas.renderAll();
}
});
canvas.on('mouse:up', function (o) {
started = false;
if (freeDrawing) {
isDown = false;
var pointer = canvas.getPointer(o.e);
if (pointer.x === origX || pointer.y === origY || obj_selecionado === true) {
canvas.remove(rect);
obj_selecionado = false;
return false;
}
}
});
});
</script>
<canvas id='canvas' width="2024" height="1024"></canvas>
Create a polyline or polygon object instead of rectangle.
DEMO
var canvas = new fabric.Canvas('c');
var points = [{x:50,y:50},{x:200,y:50},{x:200,y:160},{x:300,y:160},{x:300,y:250},{x:100,y:250},{x:100,y:125},{x:50,y:125}];
var polygon = new fabric.Polygon(points, {
stroke: 'black',
fill: ''
});
canvas.add(polygon);
canvas {
border: 1px solid #f00;
margin: 0px;
}
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.7.0/fabric.js"></script>
<canvas id="c" width="400" height="400"></canvas>
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>
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>
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.
I'm making a image editor with Fabricjs. I made a handle (blue circle) when you click it, its hide the selected object.
All is working well.... BUT:
After moving the object i can't click the blue circle
During the movement the controls and border has to be hidden.
My fiddle
var canvas = new fabric.Canvas('c', { hoverCursor: 'pointer', selection: false });
var blue = new fabric.Circle({ radius: 15, fill: '#00f', top: 300, left: 300 }); // Circle to hide / remove the object
var red = new fabric.Circle({ radius: 50, fill: '#f00', top: 100, left: 100 });
var white = new fabric.Circle({ radius: 50, fill: '#ccc', top: 300, left: 100 });
blue.hasControls = blue.hasBorders = false;
blue.visible = false;
blue.name = "blue";
canvas.add(white, red, blue);
var selObj;
canvas.on({
'mouse:down' : setHanlde,
'mouse:up' : setHanlde,
'object:moving' : moving,
'object:rotating' : updatePosition,
'object:scaling' : updatePosition,
'selection:cleared' : hideHandle,
});
function setHanlde(e) {
obj = e.target;
obj.hasControls = obj.hasBorders = true;
if(obj.name != "blue") {
selObj = obj;
obj.setCoords();
blue.setLeft(obj.oCoords.tr.x);
blue.setTop(obj.oCoords.tr.y);
blue.visible = true;
} else {
// hide / remove object
selObj.visible = false;
blue.visible = false;
canvas.deactivateAll().renderAll();
hideHandles();
}
canvas.renderAll();
}
function updatePosition() {
selObj.setCoords();
blue.setLeft(selObj.oCoords.tr.x);
blue.setTop(selObj.oCoords.tr.y);
}
function moving(e) {
e.target.hasControls = e.target.hasBorders = false;
blue.visible = false;
}
function hideHandle() {
blue.visible = false;
}
I have updated your fiddle.
Now it should work:
jsfiddle
var canvas = new fabric.Canvas('c', { hoverCursor: 'pointer', selection: false });
var blue = new fabric.Circle({ radius: 15, fill: '#00f', top: 300, left: 300 }); // Circle to hide / remove the object
var red = new fabric.Circle({ radius: 50, fill: '#f00', top: 100, left: 100 });
var white = new fabric.Circle({ radius: 50, fill: '#ccc', top: 300, left: 100 });
blue.hasControls = blue.hasBorders = false;
blue.visible = false;
blue.name = "blue";
canvas.add(white, red, blue);
var selObj;
canvas.on({
'mouse:down' : setHanlde,
'mouse:up' : setHanlde,
'object:moving' : moving,
'object:rotating' : updatePosition,
'object:scaling' : updatePosition,
'selection:cleared' : hideHandle,
'object:modified' : updatePosition
});
function setHanlde(e) {
obj = e.target;
e.target.hasControls = e.target.hasBorders = true;
if(obj.name != "blue") {
selObj = obj;
obj.setCoords();
blue.setLeft(obj.oCoords.tr.x);
blue.setTop(obj.oCoords.tr.y);
blue.visible = true;
} else {
// hide / remove object
selObj.visible = false;
blue.visible = false;
canvas.deactivateAll().renderAll();
hideHandles();
}
canvas.renderAll();
}
function updatePosition() {
selObj.setCoords();
blue.setLeft(selObj.oCoords.tr.x);
blue.setTop(selObj.oCoords.tr.y);
blue.setCoords();
}
function moving(e) {
e.target.hasControls = e.target.hasBorders = false;
blue.visible = false;
}
function hideHandle() {
blue.visible = false;
}