mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2024-12-28 00:42:54 -05:00
parent
74d188967c
commit
8fb7c41537
15 changed files with 272 additions and 135 deletions
53
examples/Worker/Main.html
Normal file
53
examples/Worker/Main.html
Normal file
|
@ -0,0 +1,53 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Shapes</title>
|
||||
<link rel="stylesheet" href="../css/style.css">
|
||||
<script type="text/javascript" src="../../dist/paper-full.js"></script>
|
||||
<script type="text/paperscript" canvas="canvas">
|
||||
if (window.Worker) { // Check if Browser supports the Worker API.
|
||||
var worker = new Worker("Worker.js");
|
||||
|
||||
// Create two paths, and send them to the worker to perform a boolean
|
||||
// operation on them.
|
||||
|
||||
var circle = new Path.Circle({
|
||||
center: [200, 200],
|
||||
radius: 100,
|
||||
fillColor: 'red'
|
||||
});
|
||||
|
||||
var rectangle = new Path.Rectangle({
|
||||
point: [200, 200],
|
||||
size: [200, 200],
|
||||
fillColor: 'blue'
|
||||
});
|
||||
|
||||
var data = [
|
||||
circle.exportJSON(),
|
||||
rectangle.exportJSON()
|
||||
];
|
||||
console.log('Sent', data);
|
||||
worker.postMessage(data);
|
||||
|
||||
// The worker sends the result back in a message, from which we can then
|
||||
// create a new path item and siplay it.
|
||||
worker.onmessage = function(event) {
|
||||
var data = event.data;
|
||||
if (data) {
|
||||
console.log('Received', data);
|
||||
var result = project.activeLayer.importJSON(data);
|
||||
result.fillColor = 'yellow';
|
||||
result.fillColor.alpha = 0.5;
|
||||
result.position += [400, 0];
|
||||
result.fullySelected = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas" resize></canvas>
|
||||
</body>
|
||||
</html>
|
14
examples/Worker/Worker.js
Normal file
14
examples/Worker/Worker.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
importScripts('../../dist/paper-full.js');
|
||||
paper.install(this);
|
||||
paper.setup([640, 480]);
|
||||
|
||||
onmessage = function(event) {
|
||||
var data = event.data;
|
||||
if (data) {
|
||||
var path1 = project.importJSON(data[0]);
|
||||
var path2 = project.importJSON(data[1]);
|
||||
console.log(path1, path2);
|
||||
var result = path1.unite(path2);
|
||||
postMessage(result.exportJSON());
|
||||
}
|
||||
};
|
|
@ -45,7 +45,7 @@
|
|||
"gulp-cached": "^1.1.0",
|
||||
"gulp-git-streamed": "^1.0.0",
|
||||
"gulp-jshint": "^2.0.0",
|
||||
"gulp-prepro": "^2.2.0",
|
||||
"gulp-prepro": "^2.3.0",
|
||||
"gulp-qunits": "^2.0.1",
|
||||
"gulp-rename": "^1.2.2",
|
||||
"gulp-shell": "^0.5.2",
|
||||
|
@ -58,7 +58,7 @@
|
|||
"jshint": "2.8.x",
|
||||
"jshint-summary": "^0.4.0",
|
||||
"merge-stream": "^1.0.0",
|
||||
"prepro": "^2.2.0",
|
||||
"prepro": "^2.3.0",
|
||||
"qunitjs": "^1.20.0",
|
||||
"require-dir": "^0.3.0",
|
||||
"resemblejs": "^2.1.0",
|
||||
|
|
|
@ -229,29 +229,33 @@ var BlendMode = new function() {
|
|||
// is sticky is not enough, as Chome 27 pretends for blend-modes to work,
|
||||
// but does not actually apply them.
|
||||
var ctx = CanvasProvider.getContext(1, 1);
|
||||
Base.each(modes, function(func, mode) {
|
||||
// Blend #330000 (51) and #aa0000 (170):
|
||||
// Multiplying should lead to #220000 (34)
|
||||
// For darken we need to reverse color parameters in order to test mode.
|
||||
var darken = mode === 'darken',
|
||||
ok = false;
|
||||
ctx.save();
|
||||
// FF 3.6 throws exception when setting globalCompositeOperation to
|
||||
// unsupported values.
|
||||
try {
|
||||
ctx.fillStyle = darken ? '#300' : '#a00';
|
||||
ctx.fillRect(0, 0, 1, 1);
|
||||
ctx.globalCompositeOperation = mode;
|
||||
if (ctx.globalCompositeOperation === mode) {
|
||||
ctx.fillStyle = darken ? '#a00' : '#300';
|
||||
if (ctx) {
|
||||
Base.each(modes, function(func, mode) {
|
||||
// Blend #330000 (51) and #aa0000 (170):
|
||||
// Multiplying should lead to #220000 (34)
|
||||
var darken = mode === 'darken',
|
||||
ok = false;
|
||||
ctx.save();
|
||||
// FF 3.6 throws exception when setting globalCompositeOperation to
|
||||
// unsupported values.
|
||||
try {
|
||||
// For darken we need to reverse color parameters in order to
|
||||
// test mode.
|
||||
ctx.fillStyle = darken ? '#300' : '#a00';
|
||||
ctx.fillRect(0, 0, 1, 1);
|
||||
ok = ctx.getImageData(0, 0, 1, 1).data[0] !== darken ? 170 : 51;
|
||||
}
|
||||
} catch (e) {}
|
||||
ctx.restore();
|
||||
nativeModes[mode] = ok;
|
||||
});
|
||||
CanvasProvider.release(ctx);
|
||||
ctx.globalCompositeOperation = mode;
|
||||
if (ctx.globalCompositeOperation === mode) {
|
||||
ctx.fillStyle = darken ? '#a00' : '#300';
|
||||
ctx.fillRect(0, 0, 1, 1);
|
||||
ok = ctx.getImageData(0, 0, 1, 1).data[0] !== darken
|
||||
? 170 : 51;
|
||||
}
|
||||
} catch (e) {}
|
||||
ctx.restore();
|
||||
nativeModes[mode] = ok;
|
||||
});
|
||||
CanvasProvider.release(ctx);
|
||||
}
|
||||
|
||||
this.process = function(mode, srcContext, dstContext, alpha, offset) {
|
||||
var srcCanvas = srcContext.canvas,
|
||||
|
|
|
@ -16,6 +16,8 @@ var CanvasProvider = {
|
|||
canvases: [],
|
||||
|
||||
getCanvas: function(width, height) {
|
||||
if (!window)
|
||||
return null;
|
||||
var canvas,
|
||||
clear = true;
|
||||
if (typeof width === 'object') {
|
||||
|
@ -49,14 +51,17 @@ var CanvasProvider = {
|
|||
},
|
||||
|
||||
getContext: function(width, height) {
|
||||
return this.getCanvas(width, height).getContext('2d');
|
||||
var canvas = this.getCanvas(width, height);
|
||||
return canvas ? canvas.getContext('2d') : null;
|
||||
},
|
||||
|
||||
// release can receive either a canvas or a context.
|
||||
release: function(obj) {
|
||||
var canvas = obj.canvas ? obj.canvas : obj;
|
||||
// We restore contexts on release(), see getCanvas()
|
||||
canvas.getContext('2d').restore();
|
||||
this.canvases.push(canvas);
|
||||
var canvas = obj && obj.canvas ? obj.canvas : obj;
|
||||
if (canvas && canvas.getContext) {
|
||||
// We restore contexts on release(), see getCanvas()
|
||||
canvas.getContext('2d').restore();
|
||||
this.canvases.push(canvas);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -64,7 +64,7 @@ var PaperScope = Base.extend(/** @lends PaperScope# */{
|
|||
if (!this.support) {
|
||||
// Set up paper.support, as an object containing properties that
|
||||
// describe the support of various features.
|
||||
var ctx = CanvasProvider.getContext(1, 1);
|
||||
var ctx = CanvasProvider.getContext(1, 1) || {};
|
||||
proto.support = {
|
||||
nativeDash: 'setLineDash' in ctx || 'mozDash' in ctx,
|
||||
nativeBlendModes: BlendMode.nativeModes
|
||||
|
@ -72,7 +72,8 @@ var PaperScope = Base.extend(/** @lends PaperScope# */{
|
|||
CanvasProvider.release(ctx);
|
||||
}
|
||||
if (!this.agent) {
|
||||
var user = window.navigator.userAgent.toLowerCase(),
|
||||
// Use self.instead of window, to cover handle web-workers too.
|
||||
var user = self.navigator.userAgent.toLowerCase(),
|
||||
// Detect basic platforms, only mac internally required for now.
|
||||
os = (/(darwin|win|mac|linux|freebsd|sunos)/.exec(user)||[])[0],
|
||||
platform = os === 'darwin' ? 'mac' : os,
|
||||
|
|
|
@ -300,7 +300,7 @@ Base.exports.PaperScript = (function() {
|
|||
// -2 required to remove function header:
|
||||
// https://code.google.com/p/chromium/issues/detail?id=331655
|
||||
offset -= 2;
|
||||
} else if (url && window.location.href.indexOf(url) === 0) {
|
||||
} else if (window && url && !window.location.href.indexOf(url)) {
|
||||
// If the code stems from the actual html page, determine the
|
||||
// offset of inlined code.
|
||||
var html = document.getElementsByTagName('html')[0].innerHTML;
|
||||
|
@ -440,7 +440,8 @@ Base.exports.PaperScript = (function() {
|
|||
if (handlers)
|
||||
code += '\nreturn { ' + handlers + ' };';
|
||||
var agent = paper.agent;
|
||||
if (agent.chrome || agent.firefox && agent.versionNumber < 40) {
|
||||
if (document && (agent.chrome
|
||||
|| agent.firefox && agent.versionNumber < 40)) {
|
||||
// On older Firefox, all error numbers inside dynamically compiled
|
||||
// code are relative to the line where the eval / compilation
|
||||
// happened. To fix this issue, we're temporarily inserting a new
|
||||
|
@ -536,7 +537,8 @@ Base.exports.PaperScript = (function() {
|
|||
}
|
||||
|
||||
function loadAll() {
|
||||
Base.each(document.getElementsByTagName('script'), loadScript);
|
||||
Base.each(document && document.getElementsByTagName('script'),
|
||||
loadScript);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -560,13 +562,15 @@ Base.exports.PaperScript = (function() {
|
|||
return script ? loadScript(script) : loadAll();
|
||||
}
|
||||
|
||||
// Catch cases where paper.js is loaded after the browser event has already
|
||||
// occurred.
|
||||
if (document.readyState === 'complete') {
|
||||
// Handle it asynchronously
|
||||
setTimeout(loadAll);
|
||||
} else {
|
||||
DomEvent.add(window, { load: loadAll });
|
||||
if (window) {
|
||||
// Catch cases where paper.js is loaded after the browser event has
|
||||
// already occurred.
|
||||
if (document.readyState === 'complete') {
|
||||
// Handle it asynchronously
|
||||
setTimeout(loadAll);
|
||||
} else {
|
||||
DomEvent.add(window, { load: loadAll });
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
@ -113,7 +113,7 @@ var DomElement = new function() {
|
|||
* prefix variants.
|
||||
*/
|
||||
getPrefixed: function(el, name) {
|
||||
return handlePrefix(el, name);
|
||||
return el && handlePrefix(el, name);
|
||||
},
|
||||
|
||||
setPrefixed: function(el, name, value) {
|
||||
|
|
|
@ -17,20 +17,27 @@
|
|||
*/
|
||||
var DomEvent = /** @lends DomEvent */{
|
||||
add: function(el, events) {
|
||||
for (var type in events) {
|
||||
var func = events[type],
|
||||
parts = type.split(/[\s,]+/g);
|
||||
for (var i = 0, l = parts.length; i < l; i++)
|
||||
el.addEventListener(parts[i], func, false);
|
||||
// Do not fail if el is not defined, that way we can keep the code that
|
||||
// should not fail in web-workers to a minimum.
|
||||
if (el) {
|
||||
for (var type in events) {
|
||||
var func = events[type],
|
||||
parts = type.split(/[\s,]+/g);
|
||||
for (var i = 0, l = parts.length; i < l; i++)
|
||||
el.addEventListener(parts[i], func, false);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
remove: function(el, events) {
|
||||
for (var type in events) {
|
||||
var func = events[type],
|
||||
parts = type.split(/[\s,]+/g);
|
||||
for (var i = 0, l = parts.length; i < l; i++)
|
||||
el.removeEventListener(parts[i], func, false);
|
||||
// See DomEvent.add() for an explanation of this check:
|
||||
if (el) {
|
||||
for (var type in events) {
|
||||
var func = events[type],
|
||||
parts = type.split(/[\s,]+/g);
|
||||
for (var i = 0, l = parts.length; i < l; i++)
|
||||
el.removeEventListener(parts[i], func, false);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
13
src/init.js
13
src/init.js
|
@ -17,5 +17,14 @@
|
|||
// their shared scope.
|
||||
|
||||
/* global document:true, window:true */
|
||||
window = window || require('./node/window');
|
||||
var document = window.document;
|
||||
// Use typeof self to detect both browsers and web-workers.
|
||||
// In workers, window will then be null, so we can use the validity of the
|
||||
// window object to decide if we're in a worker-like context in the rest of
|
||||
// the library.
|
||||
var window = self ? self.window : require('./node/window'),
|
||||
document = window && window.document;
|
||||
// Make sure 'self' always points to a window object, also on Node.js.
|
||||
// NOTE: We're not modifying the global `self` here. We receive its value passed
|
||||
// to the paper.js function scope, and this is the one that is modified here.
|
||||
self = self || window;
|
||||
|
||||
|
|
|
@ -56,9 +56,9 @@ if (typeof window === 'object') {
|
|||
prepro.setup(function() {
|
||||
// Return objects to be defined in the preprocess-scope.
|
||||
// Note that this would be merge in with already existing objects.
|
||||
// We're defining window here since the paper-scope argument is only
|
||||
// We're defining self here since the paper-scope argument is only
|
||||
// available in the included scripts when the library is actually built.
|
||||
return { __options: options, window: null };
|
||||
return { __options: options, self: undefined };
|
||||
});
|
||||
// Load constants.js, required by the on-the-fly preprocessing:
|
||||
prepro.include('../src/constants.js');
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
// Allow the minification of the undefined variable by defining it as a local
|
||||
// parameter inside the paper scope.
|
||||
var paper = function(window, undefined) {
|
||||
var paper = function(self, undefined) {
|
||||
/*#*/ include('init.js');
|
||||
// Inline Straps.js core (the Base class) inside the paper scope first:
|
||||
/*#*/ include('../node_modules/straps/straps.js');
|
||||
|
@ -123,4 +123,4 @@ var paper = function(window, undefined) {
|
|||
|
||||
/*#*/ include('export.js');
|
||||
return paper;
|
||||
}(this.window);
|
||||
}(this.self);
|
||||
|
|
|
@ -75,7 +75,7 @@ var Color = Base.extend(new function() {
|
|||
var value = +components[i];
|
||||
components[i] = i < 3 ? value / 255 : value;
|
||||
}
|
||||
} else {
|
||||
} else if (window) {
|
||||
// Named
|
||||
var cached = colorCache[string];
|
||||
if (!cached) {
|
||||
|
@ -102,6 +102,9 @@ var Color = Base.extend(new function() {
|
|||
];
|
||||
}
|
||||
components = cached.slice();
|
||||
} else {
|
||||
// Web-workers can't resolve CSS color names, for now.
|
||||
components = [0, 0, 0];
|
||||
}
|
||||
return components;
|
||||
}
|
||||
|
|
|
@ -42,16 +42,16 @@ var CanvasView = View.extend(/** @lends CanvasView# */{
|
|||
+ [].slice.call(arguments, 1));
|
||||
canvas = CanvasProvider.getCanvas(size);
|
||||
}
|
||||
var context = this._context = canvas.getContext('2d');
|
||||
var ctx = this._context = canvas.getContext('2d');
|
||||
// Save context right away, and restore in #remove(). Also restore() and
|
||||
// save() again in _setViewSize(), to prevent accumulation of scaling.
|
||||
context.save();
|
||||
// save() again in _setElementSize() to prevent accumulation of scaling.
|
||||
ctx.save();
|
||||
this._pixelRatio = 1;
|
||||
if (!/^off|false$/.test(PaperScope.getAttribute(canvas, 'hidpi'))) {
|
||||
// Hi-DPI Canvas support based on:
|
||||
// http://www.html5rocks.com/en/tutorials/canvas/hidpi/
|
||||
var deviceRatio = window.devicePixelRatio || 1,
|
||||
backingStoreRatio = DomElement.getPrefixed(context,
|
||||
backingStoreRatio = DomElement.getPrefixed(ctx,
|
||||
'backingStorePixelRatio') || 1;
|
||||
this._pixelRatio = deviceRatio / backingStoreRatio;
|
||||
}
|
||||
|
@ -63,13 +63,13 @@ var CanvasView = View.extend(/** @lends CanvasView# */{
|
|||
return remove.base.call(this);
|
||||
},
|
||||
|
||||
_setViewSize: function _setViewSize(width, height) {
|
||||
_setElementSize: function _setElementSize(width, height) {
|
||||
var pixelRatio = this._pixelRatio;
|
||||
// Upscale the canvas if the pixel ratio is more than 1.
|
||||
_setViewSize.base.call(this, width * pixelRatio, height * pixelRatio);
|
||||
_setElementSize.base.call(this, width * pixelRatio, height * pixelRatio);
|
||||
if (pixelRatio !== 1) {
|
||||
var element = this._element,
|
||||
context = this._context;
|
||||
ctx = this._context;
|
||||
// We need to set the correct size on non-resizable canvases through
|
||||
// their style when HiDPI is active, as otherwise they would appear
|
||||
// too big.
|
||||
|
@ -80,9 +80,9 @@ var CanvasView = View.extend(/** @lends CanvasView# */{
|
|||
}
|
||||
// Scale the context to counter the fact that we've manually scaled
|
||||
// our canvas element.
|
||||
context.restore();
|
||||
context.save();
|
||||
context.scale(pixelRatio, pixelRatio);
|
||||
ctx.restore();
|
||||
ctx.save();
|
||||
ctx.scale(pixelRatio, pixelRatio);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -90,18 +90,13 @@ var CanvasView = View.extend(/** @lends CanvasView# */{
|
|||
* Converts the provide size in any of the units allowed in the browser to
|
||||
* pixels.
|
||||
*/
|
||||
getPixelSize: function(size) {
|
||||
getPixelSize: function getPixelSize(size) {
|
||||
var agent = paper.agent,
|
||||
pixels;
|
||||
// Firefox doesn't appear to convert context.font sizes to pixels,
|
||||
// while other browsers do. Fall-back to View#getPixelSize.
|
||||
if (agent && agent.firefox) {
|
||||
// Firefox doesn't appear to convert context.font sizes to pixels,
|
||||
// while other browsers do. Workaround:
|
||||
var parent = this._element.parentNode,
|
||||
temp = document.createElement('div');
|
||||
temp.style.fontSize = size;
|
||||
parent.appendChild(temp);
|
||||
pixels = parseFloat(DomElement.getStyles(temp).fontSize);
|
||||
parent.removeChild(temp);
|
||||
pixels = getPixelSize.base.call(this, size);
|
||||
} else {
|
||||
var ctx = this._context,
|
||||
prevFont = ctx.font;
|
||||
|
|
156
src/view/View.js
156
src/view/View.js
|
@ -23,29 +23,6 @@ var View = Base.extend(Emitter, /** @lends View# */{
|
|||
_class: 'View',
|
||||
|
||||
initialize: function View(project, element) {
|
||||
// Store reference to the currently active global paper scope, and the
|
||||
// active project, which will be represented by this view
|
||||
this._project = project;
|
||||
this._scope = project._scope;
|
||||
this._element = element;
|
||||
// Sub-classes may set _pixelRatio first
|
||||
if (!this._pixelRatio)
|
||||
this._pixelRatio = window.devicePixelRatio || 1;
|
||||
// Generate an id for this view / element if it does not have one
|
||||
this._id = element.getAttribute('id');
|
||||
if (this._id == null)
|
||||
element.setAttribute('id', this._id = 'view-' + View._id++);
|
||||
// Install event handlers
|
||||
DomEvent.add(element, this._viewEvents);
|
||||
// Borrowed from Hammer.js:
|
||||
var none = 'none';
|
||||
DomElement.setPrefixed(element.style, {
|
||||
userDrag: none,
|
||||
userSelect: none,
|
||||
touchCallout: none,
|
||||
contentZooming: none,
|
||||
tapHighlightColor: 'rgba(0,0,0,0)'
|
||||
});
|
||||
|
||||
function getSize(name) {
|
||||
return element[name] || parseInt(element.getAttribute(name), 10);
|
||||
|
@ -63,35 +40,68 @@ var View = Base.extend(Emitter, /** @lends View# */{
|
|||
: size;
|
||||
}
|
||||
|
||||
// If the element has the resize attribute, listen to resize events and
|
||||
// update its coordinate space accordingly
|
||||
if (PaperScope.hasAttribute(element, 'resize')) {
|
||||
var that = this;
|
||||
DomEvent.add(window, this._windowEvents = {
|
||||
resize: function() {
|
||||
that.setViewSize(getCanvasSize());
|
||||
}
|
||||
var size;
|
||||
if (window && element) {
|
||||
// Generate an id for this view / element if it does not have one
|
||||
this._id = element.getAttribute('id');
|
||||
if (this._id == null)
|
||||
element.setAttribute('id', this._id = 'view-' + View._id++);
|
||||
// Install event handlers
|
||||
DomEvent.add(element, this._viewEvents);
|
||||
// Borrowed from Hammer.js:
|
||||
var none = 'none';
|
||||
DomElement.setPrefixed(element.style, {
|
||||
userDrag: none,
|
||||
userSelect: none,
|
||||
touchCallout: none,
|
||||
contentZooming: none,
|
||||
tapHighlightColor: 'rgba(0,0,0,0)'
|
||||
});
|
||||
|
||||
// If the element has the resize attribute, listen to resize events
|
||||
// and update its coordinate space accordingly
|
||||
if (PaperScope.hasAttribute(element, 'resize')) {
|
||||
var that = this;
|
||||
DomEvent.add(window, this._windowEvents = {
|
||||
resize: function() {
|
||||
that.setViewSize(getCanvasSize());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
size = getCanvasSize();
|
||||
|
||||
if (PaperScope.hasAttribute(element, 'stats')
|
||||
&& typeof Stats !== 'undefined') {
|
||||
this._stats = new Stats();
|
||||
// Align top-left to the element
|
||||
var stats = this._stats.domElement,
|
||||
style = stats.style,
|
||||
offset = DomElement.getOffset(element);
|
||||
style.position = 'absolute';
|
||||
style.left = offset.x + 'px';
|
||||
style.top = offset.y + 'px';
|
||||
document.body.appendChild(stats);
|
||||
}
|
||||
} else {
|
||||
// For web-workers: Allow calling of `paper.setup(new Size(x, y));`
|
||||
size = new Size(element);
|
||||
element = null;
|
||||
}
|
||||
// Store reference to the currently active global paper scope, and the
|
||||
// active project, which will be represented by this view
|
||||
this._project = project;
|
||||
this._scope = project._scope;
|
||||
this._element = element;
|
||||
// Sub-classes may set _pixelRatio first
|
||||
if (!this._pixelRatio)
|
||||
this._pixelRatio = window && window.devicePixelRatio || 1;
|
||||
// Set canvas size even if we just determined the size from it, since
|
||||
// it might have been set to a % size, in which case it would use some
|
||||
// default internal size (300x150 on WebKit) and scale up the pixels.
|
||||
// We also need this call here for HiDPI support.
|
||||
var size = this._viewSize = getCanvasSize();
|
||||
this._setViewSize(size.width, size.height);
|
||||
// TODO: Test this on IE:
|
||||
if (PaperScope.hasAttribute(element, 'stats')
|
||||
&& typeof Stats !== 'undefined') {
|
||||
this._stats = new Stats();
|
||||
// Align top-left to the element
|
||||
var stats = this._stats.domElement,
|
||||
style = stats.style,
|
||||
offset = DomElement.getOffset(element);
|
||||
style.position = 'absolute';
|
||||
style.left = offset.x + 'px';
|
||||
style.top = offset.y + 'px';
|
||||
document.body.appendChild(stats);
|
||||
}
|
||||
this._setElementSize(size.width, size.height);
|
||||
this._viewSize = size;
|
||||
// Keep track of views internally
|
||||
View._views.push(this);
|
||||
// Link this id to our view
|
||||
|
@ -192,14 +202,15 @@ var View = Base.extend(Emitter, /** @lends View# */{
|
|||
* @function
|
||||
* @return {Boolean} {@true if the view was updated}
|
||||
*/
|
||||
// update: function() {
|
||||
// },
|
||||
update: function() {
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the view if there are changes.
|
||||
*
|
||||
* @deprecated use {@link #update()} instead.
|
||||
*/
|
||||
// NOTE: We cannot use draw: '#update'` as that would not work on CanvasView
|
||||
draw: function() {
|
||||
this.update();
|
||||
},
|
||||
|
@ -369,8 +380,8 @@ var View = Base.extend(Emitter, /** @lends View# */{
|
|||
delta = size.subtract(this._viewSize);
|
||||
if (delta.isZero())
|
||||
return;
|
||||
this._setElementSize(width, height);
|
||||
this._viewSize.set(width, height);
|
||||
this._setViewSize(width, height);
|
||||
// Call onResize handler on any size change
|
||||
this.emit('resize', {
|
||||
size: size,
|
||||
|
@ -384,12 +395,14 @@ var View = Base.extend(Emitter, /** @lends View# */{
|
|||
/**
|
||||
* Private method, overridden in CanvasView for HiDPI support.
|
||||
*/
|
||||
_setViewSize: function(width, height) {
|
||||
_setElementSize: function(width, height) {
|
||||
var element = this._element;
|
||||
if (element.width !== width)
|
||||
element.width = width;
|
||||
if (element.height !== height)
|
||||
element.height = height;
|
||||
if (element) {
|
||||
if (element.width !== width)
|
||||
element.width = width;
|
||||
if (element.height !== height)
|
||||
element.height = height;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -482,6 +495,32 @@ var View = Base.extend(Emitter, /** @lends View# */{
|
|||
*/
|
||||
isInserted: function() {
|
||||
return DomElement.isInserted(this._element);
|
||||
},
|
||||
|
||||
// Empty stubs of #getPixelSize() and #getTextWidth(), around so that
|
||||
// web-workers don't fail. Overridden with proper functionality in
|
||||
// CanvasView.
|
||||
getPixelSize: function(size) {
|
||||
var element = this._element,
|
||||
pixels;
|
||||
if (element) {
|
||||
// this code is part of the Firefox workaround in CanvasView, but
|
||||
// also provides a way to determine pixel-size that does not involve
|
||||
// a Canvas. It still does not work in a web-worker though.
|
||||
var parent = element.parentNode,
|
||||
temp = document.createElement('div');
|
||||
temp.style.fontSize = size;
|
||||
parent.appendChild(temp);
|
||||
pixels = parseFloat(DomElement.getStyles(temp).fontSize);
|
||||
parent.removeChild(temp);
|
||||
} else {
|
||||
pixels = parseFloat(pixels);
|
||||
}
|
||||
return pixels;
|
||||
},
|
||||
|
||||
getTextWidth: function(font, lines) {
|
||||
return 0;
|
||||
}
|
||||
}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) {
|
||||
var rotate = key === 'rotate';
|
||||
|
@ -924,15 +963,18 @@ var View = Base.extend(Emitter, /** @lends View# */{
|
|||
_id: 0,
|
||||
|
||||
create: function(project, element) {
|
||||
if (typeof element === 'string')
|
||||
if (document && typeof element === 'string')
|
||||
element = document.getElementById(element);
|
||||
// Factory to provide the right View subclass for a given element.
|
||||
// Produces only CanvasViews for now:
|
||||
return new CanvasView(project, element);
|
||||
// Produces only CanvasView or View items (for workers) for now:
|
||||
var ctor = window ? CanvasView : View;
|
||||
return new ctor(project, element);
|
||||
}
|
||||
}
|
||||
},
|
||||
new function() { // Injection scope for event handling on the browser
|
||||
if (!window)
|
||||
return;
|
||||
/**
|
||||
* Native event handling, coordinate conversion, focus handling and
|
||||
* delegation to view and tool objects.
|
||||
|
|
Loading…
Reference in a new issue