Comparing version 0.1.1 to 0.2.0
{ | ||
"name": "drawable", | ||
"version": "0.1.1", | ||
"version": "0.2.0", | ||
"description": | ||
@@ -5,0 +5,0 @@ "A way to make styling canvas elements like text and images nicer", |
# Drawable | ||
A way to make styling canvas elements like text and images nicer. This lib uses `node-canvas`, please see instructions on [how to get this working](https://github.com/Automattic/node-canvas#installation) on your computer. | ||
[![Build Status](https://travis-ci.org/jcblw/drawable.svg?branch=master)](https://travis-ci.org/jcblw/drawable) | ||
> This is currently in some flux, and currently only works on a node server | ||
A way to make styling canvas elements like text and images nicer. This lib uses [node-canvas](https://github.com/Automattic/node-canvas), please see instructions on [how to get this working](https://github.com/Automattic/node-canvas#installation) on your computer. | ||
## Why | ||
The idea is to create a somewhat familiar way to style a canvas element to leverage the ability to turn the canvas drawing into an image. Images are more sharable and if done correctly more printable as well :D. This lib leverages [node-canvas](https://github.com/Automattic/node-canvas) to be able to do this server side currently, but its goal is to eventually be universal for client and server technologies. That way you could render some awesome interactive charts and then potentially render them also into something like a Github README. Not quite there yet tho. | ||
## Be careful | ||
This is currently in some flux, and currently only works on a node server. | ||
## Installation | ||
``` | ||
@@ -13,2 +23,6 @@ npm i drawable --save | ||
Drawable is really just a canvas that is meant to use some CSS like syntax to be able to add text and images to a canvas. | ||
### Creating a drawable | ||
```javascript | ||
@@ -18,19 +32,71 @@ import Drawable from 'drawable' | ||
const drawable = new Drawable({ width: 200, height: 200, backgroundColor: 'white' }); | ||
``` | ||
drawable.addFont('../font/path.ttf', 'Fake font'); | ||
There are a few styles that are passed here: `width`, `height`, and `backgroundColor`. This does exactly what you would think it would do. It makes a canvas with the width of 200px height of 200px and the backgroundColor of white. If you have used canvas before you would notice that backgroundColor is not a thing. All this is really doing is creating a rectangle that fills the background of the canvas with a fill of the color passed. By default this is `transparent`. | ||
const image = Drawable.image('../../image/path', { top: 0, left: 0 }); | ||
const text = Drawable.text('foo bar', { | ||
textAlign: 'center', | ||
##### Styles for constructor | ||
| Styles key | description | default | | ||
|-----------------|------------------------------------|-------------| | ||
| width | The width of the canvas | 0 | | ||
| height | The height of the canvas | 0 | | ||
| backgroundColor | The background color of the canvas | transparent | | ||
### Adding in some text | ||
```javascript | ||
const text = Drawable.text('Here is some text', { | ||
fontSize: 12, | ||
top: 20, | ||
left: 20, | ||
fontSize: 12, | ||
fontFamily: 'Fake font' | ||
right: 20, | ||
textAlign: 'center' | ||
}); | ||
drawable.append([image, text]); | ||
// append text to drawable instance | ||
drawable.append(text); | ||
``` | ||
console.log(drawable.toBuffer()); | ||
This is where the magic of `drawable` starts to shine. With drawable text we automatically will wrap text based on the size of the canvas and the values passed in for the `right` and `left` options. Then we calculate the alignment of the text using `textAlign` option. | ||
##### Styles for text | ||
| Styles key | Description | Default | | ||
|------------|-------------------------------------------|------------| | ||
| top | The top alignment of the text container | 0 | | ||
| left | The left alignment of the text container | 0 | | ||
| right | The right alignment of the text container | 0 | | ||
| color | The color of the text | #222 | | ||
| textAlign | Can be: 'center', 'left', or 'right' | left | | ||
| lineHeight | The line height of the text | 0 | | ||
| fontSize | The size of the text in pixels | 0 | | ||
| fontFamily | The font used in the canvas | sans-serif | | ||
### Adding in a image | ||
```javascript | ||
const image = Drawable.image('./path/to/image.jpg', { | ||
top: 20, | ||
left: 20, | ||
}); | ||
// append text to drawable instance | ||
drawable.append(image); | ||
``` | ||
Images are pretty basic, you give the image a left and top coordinate and it should render. If you are trying to emulate something like a background image you could also use the `objectFit` style which should allow you to `cover` or `contain` the image in the canvas. | ||
##### Styles for image | ||
| Styles key | Description | Default | | ||
|------------|----------------------------------------------------------------------------------------------------------------------------------|---------------| | ||
| top | The top alignment of the image | 0 | | ||
| left | The left alignment of the image | 0 | | ||
| width | The width of the image | images.width | | ||
| height | The height of the image | images.height | | ||
| objectFit | [object-fit css](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) current values supported are "cover" and "contain" | none | | ||
> Note: when using object fit it will override the left, top, width, and height values. | ||
## TODO | ||
@@ -37,0 +103,0 @@ |
import Canvas from 'canvas'; | ||
import sizeOf from 'image-size'; | ||
const { loadImage } = Canvas; | ||
@@ -12,2 +13,3 @@ | ||
return loadImage(this._img).then(image => { | ||
this._dimensions = sizeOf(this._img); | ||
this._image = image; | ||
@@ -17,2 +19,39 @@ }); | ||
getRatio(width, height) { | ||
return width / height; | ||
} | ||
getObjectFitDimensions( | ||
{ width: canvasWidth, height: canvasHeight }, | ||
objectFit | ||
) { | ||
const { width, height } = this._dimensions; | ||
const isCover = objectFit === 'cover'; | ||
const imageRatio = this.getRatio(width, height); | ||
const canvasRatio = this.getRatio(canvasWidth, canvasHeight); | ||
// contain is the cover algorithm flipped | ||
const shouldUseCanvasHeight = isCover | ||
? canvasRatio < imageRatio | ||
: canvasRatio >= imageRatio; | ||
if (shouldUseCanvasHeight) { | ||
const adjustedHeight = canvasHeight; | ||
const adjustedWidth = canvasHeight * imageRatio; | ||
return { | ||
height: adjustedHeight, | ||
width: adjustedWidth, | ||
left: (adjustedWidth - canvasWidth) / 2 * -1, | ||
top: 0, | ||
}; | ||
} else { | ||
const adjustedWidth = canvasWidth; | ||
const adjustedHeight = canvasWidth / imageRatio; | ||
return { | ||
height: adjustedHeight, | ||
width: adjustedWidth, | ||
top: (adjustedHeight - canvasHeight) / 2 * -1, | ||
left: 0, | ||
}; | ||
} | ||
} | ||
getStyleProp(prop = '') { | ||
@@ -22,15 +61,33 @@ return this._styles[prop] || 0; | ||
draw(context) { | ||
drawImage(context, canvasStyles) { | ||
const objectFit = this._styles.objectFit; | ||
let aligmentSpec; | ||
if (objectFit) { | ||
aligmentSpec = this.getObjectFitDimensions(canvasStyles, objectFit); | ||
} else { | ||
aligmentSpec = { | ||
top: this.getStyleProp('top'), | ||
left: this.getStyleProp('left'), | ||
width: this.getStyleProp('width') || this._dimensions.width, | ||
height: this.getStyleProp('height') || this._dimensions.height, | ||
}; | ||
} | ||
context.drawImage( | ||
this._image, | ||
aligmentSpec.left, | ||
aligmentSpec.top, | ||
aligmentSpec.width, | ||
aligmentSpec.height | ||
); | ||
} | ||
draw(context, canvasStyles) { | ||
if (!this._image) { | ||
return this.loadImage(this._img).then(() => { | ||
context.drawImage( | ||
this._image, | ||
this.getStyleProp('left'), | ||
this.getStyleProp('top') | ||
); | ||
this.drawImage(context, canvasStyles); | ||
return Promise.resolve(); | ||
}); | ||
} | ||
context.drawImage(this._img, 0, 0); | ||
this.drawImage(context, canvasStyles); | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
119810
12
488
106