Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-canvas

Package Overview
Dependencies
Maintainers
2
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-canvas - npm Package Compare versions

Comparing version 0.0.1 to 1.0.0

lib/__tests__/clamp-test.js

24

examples/css-layout/app.js
/** @jsx React.DOM */
var React = require('react');
var ReactDOM = require('react-dom');
var ReactCanvas = require('react-canvas');

@@ -26,3 +27,5 @@

</Text>
<Image src='http://lorempixel.com/360/420/cats/1/' style={this.getImageStyle()} fadeIn={true} />
<Group style={this.getImageGroupStyle()}>
<Image src='http://lorempixel.com/360/420/cats/1/' style={this.getImageStyle()} fadeIn={true} />
</Group>
<Text style={this.getExcerptStyle()}>

@@ -55,4 +58,5 @@ With these words the Witch fell down in a brown, melted, shapeless mass and began to spread over the clean boards of the kitchen floor. Seeing that she had really melted away to nothing, Dorothy drew another bucket of water and threw it over the mess. She then swept it all out the door. After picking out the silver shoe, which was all that was left of the old woman, she cleaned and dried it with a cloth, and put it on her foot again. Then, being at last free to do as she chose, she ran out to the courtyard to tell the Lion that the Wicked Witch of the West had come to an end, and that they were no longer prisoners in a strange land.

getImageStyle: function () {
getImageGroupStyle: function () {
return {
position: 'relative',
flex: 1,

@@ -63,6 +67,16 @@ backgroundColor: '#eee'

getImageStyle: function () {
return {
position: 'absolute',
left: 0,
top: 0,
right: 0,
bottom: 0
};
},
getTitleStyle: function () {
return {
fontFace: FontFace('Georgia'),
fontSize: 18,
fontSize: 22,
lineHeight: 28,

@@ -79,3 +93,3 @@ height: 28,

fontFace: FontFace('Georgia'),
fontSize: 12,
fontSize: 17,
lineHeight: 25,

@@ -97,2 +111,2 @@ marginTop: 15,

React.render(<App />, document.getElementById('main'));
ReactDOM.render(<App />, document.getElementById('main'));

@@ -6,2 +6,3 @@ /** @jsx React.DOM */

var React = require('react');
var ReactDOM = require('react-dom');
var ReactCanvas = require('react-canvas');

@@ -63,2 +64,2 @@ var Item = require('./components/Item');

React.render(<App />, document.getElementById('main'));
ReactDOM.render(<App />, document.getElementById('main'));

@@ -6,2 +6,3 @@ /** @jsx React.DOM */

var React = require('react');
var ReactDOM = require('react-dom');
var ReactCanvas = require('react-canvas');

@@ -73,2 +74,2 @@ var Page = require('./components/Page');

React.render(<App />, document.getElementById('main'));
ReactDOM.render(<App />, document.getElementById('main'));

@@ -94,3 +94,3 @@ /** @jsx React.DOM */

width: this.props.width - 2 * CONTENT_INSET,
fontSize: 20,
fontSize: 22,
lineHeight: 30,

@@ -106,3 +106,3 @@ fontFace: FontFace('Avenir Next Condensed, Helvetica, sans-serif', null, {weight: 500})

fontFace: FontFace('Georgia, serif'),
fontSize: 12,
fontSize: 15,
lineHeight: 23

@@ -109,0 +109,0 @@ };

var gulp = require('gulp');
var clean = require('gulp-clean');
var del = require('del');
var connect = require('gulp-connect');

@@ -7,5 +7,7 @@ var webpack = require('gulp-webpack');

var port = process.env.PORT || 8080;
var reloadPort = process.env.RELOAD_PORT || 35729;
gulp.task('clean', function () {
return gulp.src('build', {read: false})
.pipe(clean());
del(['build']);
});

@@ -21,3 +23,6 @@

connect.server({
livereload: true
port: port,
livereload: {
port: reloadPort
}
});

@@ -24,0 +29,0 @@ });

@@ -139,3 +139,3 @@ 'use strict';

ctx.fillStyle = options.color;
ctx.font = fontFace.attributes.style + ' normal ' + fontFace.attributes.weight + ' ' + options.fontSize + 'pt ' + fontFace.family;
ctx.font = fontFace.attributes.style + ' ' + fontFace.attributes.weight + ' ' + options.fontSize + 'px ' + fontFace.family;

@@ -142,0 +142,0 @@ textMetrics.lines.forEach(function (line, index) {

@@ -13,2 +13,1 @@ 'use strict';

};

@@ -8,4 +8,4 @@ 'use strict';

var ReactMultiChild = require('react/lib/ReactMultiChild');
var assign = require('react/lib/Object.assign');
var emptyObject = require('react/lib/emptyObject');
var assign = require('object-assign');
var emptyObject = require('fbjs/lib/emptyObject');

@@ -12,0 +12,0 @@ var ContainerMixin = assign({}, ReactMultiChild.Mixin, {

@@ -10,3 +10,5 @@ 'use strict';

onTouchCancel: 'touchcancel',
onClick: 'click'
onClick: 'click',
onContextMenu: 'contextmenu',
onDoubleClick: 'dblclick'
};

@@ -26,2 +26,3 @@ 'use strict';

this._currentElement = nextComponent;
this.node.invalidateLayout();
},

@@ -28,0 +29,0 @@

@@ -24,3 +24,12 @@ 'use strict';

}
return getLayerAtPoint(rootLayer, e.type, FrameUtils.make(touchX, touchY, 1, 1));
touchY = touchY - window.pageYOffset;
touchX = touchX - window.pageXOffset;
return getLayerAtPoint(
rootLayer,
e.type,
FrameUtils.make(touchX, touchY, 1, 1),
rootLayer.translateX || 0,
rootLayer.translateY || 0
);
}

@@ -52,7 +61,7 @@

*/
function getLayerAtPoint (root, type, point) {
function getLayerAtPoint (root, type, point, tx, ty) {
var layer = null;
var hitHandle = getHitHandle(type);
var sortedChildren;
var hitFrame = root.frame;
var hitFrame = FrameUtils.clone(root.frame);

@@ -68,3 +77,9 @@ // Early bail for non-visible layers

for (var i=0, len=sortedChildren.length; i < len; i++) {
layer = getLayerAtPoint(sortedChildren[i], type, point);
layer = getLayerAtPoint(
sortedChildren[i],
type,
point,
tx + (root.translateX || 0),
ty + (root.translateY || 0)
);
if (layer) {

@@ -84,2 +99,11 @@ break;

// Check for x/y translation
if (tx) {
hitFrame.x += tx;
}
if (ty) {
hitFrame.y += ty;
}
// No child layer at the given point. Try the parent layer.

@@ -86,0 +110,0 @@ if (!layer && root[hitHandle] && FrameUtils.intersects(hitFrame, point)) {

@@ -37,2 +37,3 @@ 'use strict';

this._currentElement = nextComponent;
this.node.invalidateLayout();
},

@@ -80,2 +81,4 @@

var imageStyle = assign({}, this.props.style);
var style = assign({}, this.props.style);
var backgroundStyle = assign({}, this.props.style);
var useBackingStore = this.state.loaded ? this.props.useBackingStore : false;

@@ -86,4 +89,10 @@

// Hide opaque background if image loaded so that images with transparent
// do not render on top of solid color.
style.backgroundColor = imageStyle.backgroundColor = null;
backgroundStyle.alpha = clamp(1 - this.state.imageAlpha, 0, 1);
return (
React.createElement(Group, {ref: 'main', style: this.props.style},
React.createElement(Group, {ref: 'main', style: style},
React.createElement(Layer, {ref: 'background', style: backgroundStyle}),
React.createElement(RawImage, {ref: 'image', src: this.props.src, style: imageStyle, useBackingStore: useBackingStore})

@@ -90,0 +99,0 @@ )

@@ -13,2 +13,3 @@ 'use strict';

this._img.onerror = this.emit.bind(this, 'error');
this._img.crossOrigin = true;
this._img.src = src;

@@ -81,12 +82,61 @@

var kInstancePoolLength = 300;
var _instancePool = [];
function getPooledImage (src) {
for (var i=0, len=_instancePool.length; i < len; i++) {
if (_instancePool[i].getOriginalSrc() === src) {
return _instancePool[i];
var _instancePool = {
length: 0,
// Keep all the nodes in memory.
elements: {
},
// Push with 0 frequency
push: function (hash, data) {
this.length++;
this.elements[hash] = {
hash: hash, // Helps identifying
freq: 0,
data: data
};
},
get: function (path) {
var element = this.elements[path];
if( element ){
element.freq++;
return element.data;
}
return null;
},
// used to explicitely remove the path
removeElement: function (path) {
// Now almighty GC can claim this soul
var element = this.elements[path];
delete this.elements[path];
this.length--;
return element;
},
_reduceLeastUsed: function (least, currentHash) {
var current = _instancePool.elements[currentHash];
if( least.freq > current.freq ){
return current;
}
return least;
},
popLeastUsed: function () {
var reducer = _instancePool._reduceLeastUsed;
var minUsed = Object.keys(this.elements).reduce(reducer, { freq: Infinity });
if( minUsed.hash ){
return this.removeElement(minUsed.hash);
}
return null;
}
return null;
}
};

@@ -101,10 +151,10 @@ var ImageCache = {

get: function (src) {
var image = getPooledImage(src);
var image = _instancePool.get(src);
if (!image) {
// Simple FIFO queue
// Awesome LRU
image = new Img(src);
if (_instancePool.length >= kInstancePoolLength) {
_instancePool.shift().destructor();
_instancePool.popLeastUsed().destructor();
}
_instancePool.push(image);
_instancePool.push(image.getOriginalSrc(), image);
}

@@ -111,0 +161,0 @@ return image;

@@ -20,2 +20,3 @@ 'use strict';

this._currentElement = nextComponent;
this.node.invalidateLayout();
}

@@ -22,0 +23,0 @@

@@ -56,2 +56,3 @@ 'use strict';

layer.borderColor = style.borderColor;
layer.borderWidth = style.borderWidth;
layer.borderRadius = style.borderRadius;

@@ -84,7 +85,2 @@ layer.clipRect = style.clipRect;

unmountComponent: function() {
// Purge backing stores on unmount.
var layer = this.node;
if (layer.backingStoreId) {
DrawingUtils.invalidateBackingStore(layer.backingStoreId);
}
this.destroyEventListeners();

@@ -91,0 +87,0 @@ }

@@ -40,3 +40,3 @@ 'use strict';

node.children.forEach(function (child) {
walkNode(child, node.layout.left, node.layout.top);
walkNode(child, node.layer.frame.x, node.layer.frame.y);
});

@@ -43,0 +43,0 @@ }

@@ -5,2 +5,3 @@ 'use strict';

var FontUtils = require('./FontUtils');
var LineBreaker = require('linebreak');

@@ -17,6 +18,2 @@ var canvas = document.createElement('canvas');

function splitText (text) {
return text.split(' ');
}
function getCacheKey (text, width, fontFace, fontSize, lineHeight) {

@@ -54,4 +51,7 @@ return text + width + fontFace.id + fontSize + lineHeight;

var currentLine;
var breaker;
var bk;
var lastBreak;
ctx.font = fontFace.attributes.style + ' normal ' + fontFace.attributes.weight + ' ' + fontSize + 'pt ' + fontFace.family;
ctx.font = fontFace.attributes.style + ' ' + fontFace.attributes.weight + ' ' + fontSize + 'px ' + fontFace.family;
textMetrics = ctx.measureText(text);

@@ -69,13 +69,14 @@

measuredSize.width = width;
words = splitText(text);
currentLine = '';
// This needs to be optimized!
while (words.length) {
tryLine = currentLine + words[0] + ' ';
breaker = new LineBreaker(text);
while (bk = breaker.nextBreak()) {
var word = text.slice(lastBreak ? lastBreak.position : 0, bk.position);
tryLine = currentLine + word;
textMetrics = ctx.measureText(tryLine);
if (textMetrics.width > width) {
if (textMetrics.width > width || (lastBreak && lastBreak.required)) {
measuredSize.height += lineHeight;
measuredSize.lines.push({width: lastMeasuredWidth, text: currentLine.trim()});
currentLine = words[0] + ' ';
currentLine = word;
lastMeasuredWidth = ctx.measureText(currentLine.trim()).width;

@@ -86,8 +87,11 @@ } else {

}
if (words.length === 1) {
textMetrics = ctx.measureText(currentLine.trim());
measuredSize.lines.push({width: textMetrics.width, text: currentLine.trim()});
}
words.shift();
lastBreak = bk;
}
currentLine = currentLine.trim();
if (currentLine.length > 0) {
textMetrics = ctx.measureText(currentLine);
measuredSize.lines.push({width: textMetrics, text: currentLine});
}
}

@@ -94,0 +98,0 @@

@@ -5,3 +5,3 @@ 'use strict';

var ReactUpdates = require('react/lib/ReactUpdates');
var invariant = require('react/lib/invariant');
var invariant = require('fbjs/lib/invariant');
var ContainerMixin = require('./ContainerMixin');

@@ -110,3 +110,5 @@ var RenderLayer = require('./RenderLayer');

onTouchCancel: this.handleTouchEnd,
onClick: this.handleClick})
onClick: this.handleClick,
onContextMenu: this.handleContextMenu,
onDoubleClick: this.handleDoubleClick})
);

@@ -123,3 +125,3 @@ },

) : invariant(this.isMounted()));
return this.refs.canvas.getDOMNode().getContext('2d');
return this.refs.canvas.getContext('2d');
},

@@ -151,4 +153,4 @@

if (this._pendingTick) {
this.tick();
this._pendingTick = false;
this.batchedTick();
}

@@ -175,3 +177,3 @@ },

hitTest: function (e) {
var hitTarget = hitTest(e, this.node, this.getDOMNode());
var hitTarget = hitTest(e, this.node, this.refs.canvas);
if (hitTarget) {

@@ -183,3 +185,3 @@ hitTarget[hitTest.getHitHandle(e.type)](e);

handleTouchStart: function (e) {
var hitTarget = hitTest(e, this.node, this.getDOMNode());
var hitTarget = hitTest(e, this.node, this.refs.canvas);
var touch;

@@ -221,6 +223,14 @@ if (hitTarget) {

this.hitTest(e);
}
},
handleContextMenu: function (e) {
this.hitTest(e);
},
handleDoubleClick: function (e) {
this.hitTest(e);
},
});
module.exports = Surface;

@@ -36,2 +36,3 @@ 'use strict';

this._currentElement = nextComponent;
this.node.invalidateLayout();
}

@@ -38,0 +39,0 @@

{
"name": "react-canvas",
"version": "0.0.1",
"version": "1.0.0",
"description": "High performance <canvas> rendering for React components",

@@ -11,3 +11,4 @@ "main": "lib/ReactCanvas.js",

"scripts": {
"start": "./node_modules/.bin/gulp"
"start": "./node_modules/.bin/gulp",
"test": "./node_modules/.bin/jest"
},

@@ -25,18 +26,24 @@ "keywords": [

"devDependencies": {
"react": "^0.13.0-beta.1",
"webpack": "^1.5.3",
"transform-loader": "^0.2.1",
"brfs": "^1.4.0",
"del": "^1.1.1",
"envify": "^3.2.0",
"jsx-loader": "^0.12.2",
"gulp": "^3.8.10",
"gulp-connect": "^2.2.0",
"gulp-webpack": "^1.2.0",
"gulp-clean": "^0.3.1"
"jest-cli": "^0.2.2",
"jsx-loader": "^0.12.2",
"react": "^0.14.0",
"react-dom": "^0.14.0",
"transform-loader": "^0.2.1",
"webpack": "^1.5.3"
},
"peerDependencies": {
"react": "^0.13.0-beta.1"
"react": "^0.14.0"
},
"dependencies": {
"fbjs": "^0.4.0",
"linebreak": "^0.3.0",
"object-assign": "^4.0.1",
"scroller": "git://github.com/mjohnston/scroller"
}
}

@@ -11,3 +11,3 @@ # react-canvas

Having a long history of building interfaces geared toward mobile devices, we found that the reason mobile web apps feel slow when compared to native apps is the DOM. CSS animations and transitions are the fastest path to smooth animations on the web, but they have several limitiations. React Canvas leverages the fact that most modern mobile browsers now have hardware accelerated canvas.
Having a long history of building interfaces geared toward mobile devices, we found that the reason mobile web apps feel slow when compared to native apps is the DOM. CSS animations and transitions are the fastest path to smooth animations on the web, but they have several limitations. React Canvas leverages the fact that most modern mobile browsers now have hardware accelerated canvas.

@@ -179,4 +179,9 @@ While there have been other attempts to bind canvas drawing APIs to React, they are more focused on visualizations and games. Where React Canvas differs is in the focus on building application user interfaces. The fact that it renders to canvas is an implementation detail.

This will start a live reloading server on port 8080.
This will start a live reloading server on port 8080. To override the default server and live reload ports, run `npm start` with PORT and/or RELOAD_PORT environment variables.
**A note on NODE_ENV and React**: running the examples with `NODE_ENV=production` will noticeably improve scrolling performance. This is because React skips propType validation in production mode.
## Contributing
We welcome pull requests for bug fixes, new features, and improvements to React Canvas. Contributors to the main repository must accept Flipboard's Apache-style [Individual Contributor License Agreement (CLA)](https://docs.google.com/forms/d/1gh9y6_i8xFn6pA15PqFeye19VqasuI9-bGp_e0owy74/viewform) before any changes can be merged.

@@ -19,2 +19,5 @@ module.exports = {

{ test: /\.js$/, loader: 'jsx-loader!transform/cacheable?envify' },
],
postLoaders: [
{ loader: "transform?brfs" }
]

@@ -21,0 +24,0 @@ },

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc