mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-03-15 17:29:52 -04:00
Implement a first version of drawing path selection.
This commit is contained in:
parent
74cee4abef
commit
be9f312110
3 changed files with 176 additions and 70 deletions
|
@ -56,6 +56,17 @@ var Document = this.Document = Base.extend({
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getSelectionContext: function(param) {
|
||||||
|
var context = this._selectionContext;
|
||||||
|
if (!context) {
|
||||||
|
var canvas = CanvasProvider.getCanvas(this.size);
|
||||||
|
context = this._selectionContext = canvas.getContext('2d');
|
||||||
|
context.strokeWidth = 1;
|
||||||
|
}
|
||||||
|
context.strokeStyle = context.fillStyle = param.layerColor;
|
||||||
|
return context;
|
||||||
|
},
|
||||||
|
|
||||||
draw: function() {
|
draw: function() {
|
||||||
if (this.canvas) {
|
if (this.canvas) {
|
||||||
// Initial tests conclude that clearing the canvas using clearRect
|
// Initial tests conclude that clearing the canvas using clearRect
|
||||||
|
@ -66,9 +77,21 @@ var Document = this.Document = Base.extend({
|
||||||
this.context.save();
|
this.context.save();
|
||||||
var param = { offset: new Point(0, 0) };
|
var param = { offset: new Point(0, 0) };
|
||||||
for (var i = 0, l = this.layers.length; i < l; i++) {
|
for (var i = 0, l = this.layers.length; i < l; i++) {
|
||||||
|
// TODO: use Layer#color:
|
||||||
|
param.layerColor = '#4f7aff';
|
||||||
Item.draw(this.layers[i], this.context, param);
|
Item.draw(this.layers[i], this.context, param);
|
||||||
}
|
}
|
||||||
this.context.restore();
|
this.context.restore();
|
||||||
|
|
||||||
|
// If, during drawing, one of the paths was selected, there will
|
||||||
|
// be a selectionContext which needs to be composited onto the
|
||||||
|
// canvas:
|
||||||
|
if (this._selectionContext) {
|
||||||
|
var canvas = this._selectionContext.canvas;
|
||||||
|
this.context.drawImage(canvas, 0, 0);
|
||||||
|
CanvasProvider.returnCanvas(canvas);
|
||||||
|
this._selectionContext = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,29 @@ var Item = this.Item = Base.extend({
|
||||||
return copy;
|
return copy;
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: isSelected / setSelected
|
setSelected: function(selected) {
|
||||||
|
if (this._children) {
|
||||||
|
for (var i = 0, l = this.children.length; i < l; i++) {
|
||||||
|
var child = this._children[i];
|
||||||
|
child.setSelected(selected);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this._selected = selected;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getSelected: function() {
|
||||||
|
if (this._children) {
|
||||||
|
for (var i = 0, l = this._children.length; i < l; i++) {
|
||||||
|
var child = this._children[i];
|
||||||
|
if (child.getSelected())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return !!this._selected;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// TODO: isFullySelected / setFullySelected
|
// TODO: isFullySelected / setFullySelected
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -650,11 +672,14 @@ var Item = this.Item = Base.extend({
|
||||||
// on the temporary canvas.
|
// on the temporary canvas.
|
||||||
context.translate(-itemOffset.x, -itemOffset.y);
|
context.translate(-itemOffset.x, -itemOffset.y);
|
||||||
}
|
}
|
||||||
|
var savedOffset;
|
||||||
item.draw(context, {
|
if (itemOffset) {
|
||||||
offset: itemOffset || param.offset,
|
savedOffset = param.offset;
|
||||||
compound: param.compound
|
param.offset = itemOffset;
|
||||||
});
|
}
|
||||||
|
item.draw(context, param);
|
||||||
|
if (itemOffset)
|
||||||
|
param.offset = savedOffset;
|
||||||
|
|
||||||
// If we created a temporary canvas before, composite it onto the
|
// If we created a temporary canvas before, composite it onto the
|
||||||
// parent canvas:
|
// parent canvas:
|
||||||
|
|
|
@ -99,13 +99,13 @@ var Path = this.Path = PathItem.extend({
|
||||||
return segment;
|
return segment;
|
||||||
},
|
},
|
||||||
|
|
||||||
add: function() {
|
add: function(segment) {
|
||||||
var segment = Segment.read(arguments);
|
segment = Segment.read(arguments);
|
||||||
return segment ? this._add(segment) : null;
|
return segment ? this._add(segment) : null;
|
||||||
},
|
},
|
||||||
|
|
||||||
insert: function(index, segment) {
|
insert: function(index, segment) {
|
||||||
var segment = Segment.read(arguments, 1);
|
segment = Segment.read(arguments, 1);
|
||||||
return segment ? this._add(segment, index) : null;
|
return segment ? this._add(segment, index) : null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -248,8 +248,50 @@ var Path = this.Path = PathItem.extend({
|
||||||
return loc
|
return loc
|
||||||
? loc.getCurve().getNormal(loc.getParameter())
|
? loc.getCurve().getNormal(loc.getParameter())
|
||||||
: null;
|
: null;
|
||||||
},
|
}
|
||||||
|
}, new function() { // Scope for drawing
|
||||||
|
|
||||||
|
function drawHandles(ctx, segments) {
|
||||||
|
for (var i = 0, l = segments.length; i < l; i++) {
|
||||||
|
var segment = segments[i],
|
||||||
|
handleIn = segment.handleIn,
|
||||||
|
handleOut = segment.handleOut,
|
||||||
|
point = segment.point,
|
||||||
|
rounded = point.round();
|
||||||
|
// TODO: draw handles depending on selection state of
|
||||||
|
// segment.point and neighbouring segments.
|
||||||
|
drawHandle(ctx, point, handleIn);
|
||||||
|
drawHandle(ctx, point, handleOut);
|
||||||
|
// Draw a rectangle at segment.point:
|
||||||
|
ctx.save();
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.rect(rounded.x - 2, rounded.y - 2, 4, 4);
|
||||||
|
ctx.fill();
|
||||||
|
// TODO: Only draw white rectangle if point.isSelected()
|
||||||
|
// is false:
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.rect(rounded.x - 1, rounded.y - 1, 2, 2);
|
||||||
|
ctx.fillStyle = '#ffffff';
|
||||||
|
ctx.fill();
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawHandle(ctx, point, handle) {
|
||||||
|
if (!handle.isZero()) {
|
||||||
|
handle = handle.add(point);
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(point.x, point.y);
|
||||||
|
ctx.lineTo(handle.x, handle.y);
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.beginPath();
|
||||||
|
var rounded = handle.round();
|
||||||
|
ctx.rect(rounded.x - 1, rounded.y - 1, 2, 2);
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
draw: function(ctx, param) {
|
draw: function(ctx, param) {
|
||||||
if (!param.compound)
|
if (!param.compound)
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
|
@ -292,6 +334,12 @@ var Path = this.Path = PathItem.extend({
|
||||||
// stroke, there is no need to continue.
|
// stroke, there is no need to continue.
|
||||||
var fillColor = this.getFillColor(),
|
var fillColor = this.getFillColor(),
|
||||||
strokeColor = this.getStrokeColor();
|
strokeColor = this.getStrokeColor();
|
||||||
|
// If we are drawing onto the selection canvas, stroke the
|
||||||
|
// path and draw its handles.
|
||||||
|
if (param.selection) {
|
||||||
|
ctx.stroke();
|
||||||
|
drawHandles(ctx, this.segments);
|
||||||
|
} else {
|
||||||
if (!param.compound && (fillColor || strokeColor)) {
|
if (!param.compound && (fillColor || strokeColor)) {
|
||||||
this.setContextStyles(ctx);
|
this.setContextStyles(ctx);
|
||||||
ctx.save();
|
ctx.save();
|
||||||
|
@ -310,7 +358,17 @@ var Path = this.Path = PathItem.extend({
|
||||||
}
|
}
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
}
|
}
|
||||||
|
// If the path is selected, draw it again on the separate
|
||||||
|
// selection canvas, which will be composited onto the canvas
|
||||||
|
// after drawing of the document is complete.
|
||||||
|
if (this.getSelected()) {
|
||||||
|
param.selection = true;
|
||||||
|
this.draw(this.document.getSelectionContext(param), param);
|
||||||
|
param.selection = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}, new function() { // Scope for segments list change detection
|
}, new function() { // Scope for segments list change detection
|
||||||
|
|
||||||
var segmentsFields = Base.each(
|
var segmentsFields = Base.each(
|
||||||
|
|
Loading…
Reference in a new issue