UNPKG

14.4 kBMarkdownView Raw
1<p align="center">
2 <img width="120"src="https://jlmak.es/logos/svg/rematrix.svg?v=2">
3</p>
4<p align="center">Matrix transformation made easy.</p>
5<p align="center">
6 <a href="https://travis-ci.org/jlmakes/rematrix"><img src="https://img.shields.io/travis/jlmakes/rematrix.svg" alt="Travis CI latest build status"></a>
7 <a href="https://coveralls.io/github/jlmakes/rematrix"><img src="https://img.shields.io/coveralls/jlmakes/rematrix.svg" alt="Code coverage as an up-to-date percentage"></a>
8 <a href="https://www.npmjs.com/package/rematrix"><img src="https://img.shields.io/npm/v/rematrix.svg" alt="Latest version released on Node Package Manager"></a>
9 <img src="https://img.shields.io/badge/min+gzip-1.15KB-blue.svg" alt="">
10 <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/npm/l/rematrix.svg" alt="MIT License"></a>
11</p>
12<p align="center">
13 <a href="https://saucelabs.com/u/rematrix">
14 <img src="https://saucelabs.com/browser-matrix/rematrix.svg" alt="MIT License">
15 </a>
16</p>
17
18<br>
19
20<br>
21
22# Introduction
23
24Imagine a HTML element that may have a CSS transform applied. If we want to add 45° of Z-rotation, we have no way to handle this safely in CSS—we’d just risk overwriting an existing transform. So we decide to use JavaScript, and check the current transform...
25
26`getComputedStyle(element)` returns the computed styles, and inspecting the `transform` property shows:
27
28```js
29'matrix3d(0.707107, 0.707107, 0, 0, -0.707107, 0.707107, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)'
30```
31
32It’s here we discover that browsers actually use [transformation matrices](https://en.wikipedia.org/wiki/Transformation_matrix) under the hood to describe rotation, translation, scale and shear. This means if we wish to manage CSS transforms with JavaScript (without overwriting existing transformations), we’re stuck working with matrices.
33
34**Rematrix** is an easy way to create and combine matrix transformations that work seamlessly with CSS.
35
36<br>
37
38# Installation
39
40## Browser
41
42You can paste this snippet for the minified distribution directly into your page:
43
44```html
45<script src="https://unpkg.com/rematrix/dist/rematrix.min.js"></script>
46```
47
48This will create the global variable `Rematrix`.
49
50## Module
51
52```bash
53npm install rematrix --save
54```
55
56#### CommonJS
57
58```bash
59const Rematrix = require('rematrix')
60```
61
62#### ES2015
63
64```bash
65import * as Rematrix from 'rematrix'
66```
67
68<br>
69
70# Guide
71
72<br>
73
74## Creating Transforms
75
76Most API methods look a lot like CSS, so for example, in CSS if we would write `transform: rotateZ(45deg)`, we can create the same transformation in JavaScript using Rematrix like this:
77
78```js
79Rematrix.rotateZ(45)
80```
81
82This returns a 45° rotation along the Z-axis, represented as an array of 16 values:
83
84```js
85[0.707107, 0.707107, 0, 0, -0.707107, 0.707107, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
86```
87
88These 16 values represent our **transformation matrix** in [column-major order](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/matrix3d).
89
90<br>
91
92## Combining Transforms (Using Multiplication)
93
94Where Rematrix really outshines CSS, is the ability to combine transforms — using **matrix multiplication**. We’ll recreate the same 45° rotation along the Z-axis, but using separate matrices this time:
95
96```js
97var r1 = Rematrix.rotateZ(20)
98var r2 = Rematrix.rotateZ(25)
99
100var product = Rematrix.multiply(r1, r2)
101```
102
103Here `product` describes the same array of 16 values (seen above):
104
105```js
106[0.707107, 0.707107, 0, 0, -0.707107, 0.707107, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
107```
108
109#### Better Multiplication (Using Reduce)
110
111There’s a good chance we’ll need to multiply quite a few matrices together, so its helpful to store them in an array in order to use `Array.prototype.reduce` to multiply them all in one line:
112
113```js
114var r1 = Rematrix.rotateZ(20)
115var r2 = Rematrix.rotateZ(65)
116var r3 = Rematrix.rotateZ(-40)
117
118var product = [r1, r2, r3].reduce(Rematrix.multiply)
119```
120
121> Order is very important. For example, rotating 45° along the Z-axis, followed by translating 500 pixels along the Y-axis... is not the same as translating 500 pixels along the Y-axis, followed by rotating 45° along on the Z-axis.
122
123## Preserving Transforms
124
125Before applying any of our transforms, we should capture the existing transform of our element using the `Rematrix.parse()` method:
126
127```js
128var element = document.querySelector('#example')
129var style = getComputedStyle(element)['transform']
130
131var transform = Rematrix.parse(style)
132
133var r1 = Rematrix.rotateZ(20)
134var r2 = Rematrix.rotateZ(65)
135var r3 = Rematrix.rotateZ(-40)
136
137var product = [transform, r1, r2, r3].reduce(Rematrix.multiply)
138```
139
140By simply passing the computed transform styles to `Rematrix.parse()`, we create a matrix of the existing transform. We can now factor this into our multiplication.
141
142> The existing transformation has been *deliberately* placed at the start of the array to ensure the computed transform is the foundation for the succeeding transformations.
143
144
145## Applying Transforms
146
147We need only to turn our matrix back into a string of CSS:
148
149```js
150var css = 'transform: matrix3d(' + product.join(', ') + ');'
151```
152
153From here it’s up to you how to use the CSS, but for simplicity’s sake here, we’ll just apply it inline to our element:
154
155```js
156element.setAttribute('style', css)
157```
158
159#### _And that concludes this introduction to Rematrix. Please explore the finished [Live Demo on JSFiddle](https://jsfiddle.net/a8j2oyy5/)._
160
161<br>
162
163<a name="module_Rematrix"></a>
164
165# API Reference
166
167* [Rematrix](#module_Rematrix)
168 * [.format(source)](#module_Rematrix.format)
169 * [.identity()](#module_Rematrix.identity)
170 * [.inverse(source)](#module_Rematrix.inverse)
171 * [.multiply(m, x)](#module_Rematrix.multiply)
172 * [.parse(source)](#module_Rematrix.parse)
173 * [.rotateX(angle)](#module_Rematrix.rotateX)
174 * [.rotateY(angle)](#module_Rematrix.rotateY)
175 * [.rotateZ(angle)](#module_Rematrix.rotateZ)
176 * [.scale(scalarX, [scalarY])](#module_Rematrix.scale)
177 * [.scaleX(scalar)](#module_Rematrix.scaleX)
178 * [.scaleY(scalar)](#module_Rematrix.scaleY)
179 * [.scaleZ(scalar)](#module_Rematrix.scaleZ)
180 * [.skew(angleX, [angleY])](#module_Rematrix.skew)
181 * [.skewX(angle)](#module_Rematrix.skewX)
182 * [.skewY(angle)](#module_Rematrix.skewY)
183 * [.translate(distanceX, [distanceY])](#module_Rematrix.translate)
184 * [.translateX(distance)](#module_Rematrix.translateX)
185 * [.translateY(distance)](#module_Rematrix.translateY)
186 * [.translateZ(distance)](#module_Rematrix.translateZ)
187
188<a name="module_Rematrix.format"></a>
189
190<br>
191
192### Rematrix.format(source) ⇒ <code>array</code>
193Transformation matrices in the browser come in two flavors:
194
195 - `matrix` using 6 values (short)
196 - `matrix3d` using 16 values (long)
197
198This utility follows this [conversion guide](https://goo.gl/EJlUQ1)
199to expand short form matrices to their equivalent long form.
200
201**Kind**: static method of <code>[Rematrix](#module_Rematrix)</code>
202
203| Param | Type | Description |
204| --- | --- | --- |
205| source | <code>array</code> | Accepts both short and long form matrices. |
206
207<a name="module_Rematrix.identity"></a>
208
209<br>
210
211### Rematrix.identity() ⇒ <code>array</code>
212Returns a matrix representing no transformation. The product of any matrix
213multiplied by the identity matrix will be the original matrix.
214
215> **Tip:** Similar to how `5 * 1 === 5`, where `1` is the identity number.
216
217**Kind**: static method of <code>[Rematrix](#module_Rematrix)</code>
218<a name="module_Rematrix.inverse"></a>
219
220<br>
221
222### Rematrix.inverse(source) ⇒ <code>array</code>
223Returns a matrix describing the inverse transformation of the source
224matrix. When a transformation is combined with its inverse, the product
225is the identity matrix (ie. no transformation).
226
227**Kind**: static method of <code>[Rematrix](#module_Rematrix)</code>
228
229| Param | Type | Description |
230| --- | --- | --- |
231| source | <code>array</code> | Accepts both short and long form matrices. |
232
233<a name="module_Rematrix.multiply"></a>
234
235<br>
236
237### Rematrix.multiply(m, x) ⇒ <code>array</code>
238Returns a 4x4 matrix describing the combined transformations
239of both arguments.
240
241> **Note:** Order is very important. For example, rotating 45°
242along the Z-axis, followed by translating 500 pixels along the
243Y-axis... is not the same as translating 500 pixels along the
244Y-axis, followed by rotating 45° along on the Z-axis.
245
246**Kind**: static method of <code>[Rematrix](#module_Rematrix)</code>
247
248| Param | Type | Description |
249| --- | --- | --- |
250| m | <code>array</code> | Accepts both short and long form matrices. |
251| x | <code>array</code> | Accepts both short and long form matrices. |
252
253<a name="module_Rematrix.parse"></a>
254
255<br>
256
257### Rematrix.parse(source) ⇒ <code>array</code>
258Attempts to return a 4x4 matrix describing the CSS transform matrix passed
259in, but will return the identity matrix as a fallback.
260
261**Tip:** In virtually all cases, this method is used to convert a CSS matrix
262(retrieved as a string from computed styles) to its equivalent array format.
263
264**Kind**: static method of <code>[Rematrix](#module_Rematrix)</code>
265
266| Param | Type | Description |
267| --- | --- | --- |
268| source | <code>string</code> | String containing a valid CSS `matrix` or `matrix3d` property. |
269
270<a name="module_Rematrix.rotateX"></a>
271
272<br>
273
274### Rematrix.rotateX(angle) ⇒ <code>array</code>
275Returns a 4x4 matrix describing X-axis rotation.
276
277**Kind**: static method of <code>[Rematrix](#module_Rematrix)</code>
278
279| Param | Type | Description |
280| --- | --- | --- |
281| angle | <code>number</code> | Measured in degrees. |
282
283<a name="module_Rematrix.rotateY"></a>
284
285<br>
286
287### Rematrix.rotateY(angle) ⇒ <code>array</code>
288Returns a 4x4 matrix describing Y-axis rotation.
289
290**Kind**: static method of <code>[Rematrix](#module_Rematrix)</code>
291
292| Param | Type | Description |
293| --- | --- | --- |
294| angle | <code>number</code> | Measured in degrees. |
295
296<a name="module_Rematrix.rotateZ"></a>
297
298<br>
299
300### Rematrix.rotateZ(angle) ⇒ <code>array</code>
301Returns a 4x4 matrix describing Z-axis rotation.
302
303**Kind**: static method of <code>[Rematrix](#module_Rematrix)</code>
304
305| Param | Type | Description |
306| --- | --- | --- |
307| angle | <code>number</code> | Measured in degrees. |
308
309<a name="module_Rematrix.scale"></a>
310
311<br>
312
313### Rematrix.scale(scalarX, [scalarY]) ⇒ <code>array</code>
314Returns a 4x4 matrix describing 2D scaling. The first argument
315is used for both X and Y-axis scaling, unless an optional
316second argument is provided to explicitly define Y-axis scaling.
317
318**Kind**: static method of <code>[Rematrix](#module_Rematrix)</code>
319
320| Param | Type | Description |
321| --- | --- | --- |
322| scalarX | <code>number</code> | Decimal multiplier. |
323| [scalarY] | <code>number</code> | Decimal multiplier. |
324
325<a name="module_Rematrix.scaleX"></a>
326
327<br>
328
329### Rematrix.scaleX(scalar) ⇒ <code>array</code>
330Returns a 4x4 matrix describing X-axis scaling.
331
332**Kind**: static method of <code>[Rematrix](#module_Rematrix)</code>
333
334| Param | Type | Description |
335| --- | --- | --- |
336| scalar | <code>number</code> | Decimal multiplier. |
337
338<a name="module_Rematrix.scaleY"></a>
339
340<br>
341
342### Rematrix.scaleY(scalar) ⇒ <code>array</code>
343Returns a 4x4 matrix describing Y-axis scaling.
344
345**Kind**: static method of <code>[Rematrix](#module_Rematrix)</code>
346
347| Param | Type | Description |
348| --- | --- | --- |
349| scalar | <code>number</code> | Decimal multiplier. |
350
351<a name="module_Rematrix.scaleZ"></a>
352
353<br>
354
355### Rematrix.scaleZ(scalar) ⇒ <code>array</code>
356Returns a 4x4 matrix describing Z-axis scaling.
357
358**Kind**: static method of <code>[Rematrix](#module_Rematrix)</code>
359
360| Param | Type | Description |
361| --- | --- | --- |
362| scalar | <code>number</code> | Decimal multiplier. |
363
364<a name="module_Rematrix.skew"></a>
365
366<br>
367
368### Rematrix.skew(angleX, [angleY]) ⇒ <code>array</code>
369Returns a 4x4 matrix describing shear. The first argument as
370is used for both X and Y-axis shearing, unless an optional
371second argument is provided to explicitly define Y-axis shearing.
372
373**Kind**: static method of <code>[Rematrix](#module_Rematrix)</code>
374
375| Param | Type | Description |
376| --- | --- | --- |
377| angleX | <code>number</code> | Measured in degrees. |
378| [angleY] | <code>number</code> | Measured in degrees. |
379
380<a name="module_Rematrix.skewX"></a>
381
382<br>
383
384### Rematrix.skewX(angle) ⇒ <code>array</code>
385Returns a 4x4 matrix describing X-axis shear.
386
387**Kind**: static method of <code>[Rematrix](#module_Rematrix)</code>
388
389| Param | Type | Description |
390| --- | --- | --- |
391| angle | <code>number</code> | Measured in degrees. |
392
393<a name="module_Rematrix.skewY"></a>
394
395<br>
396
397### Rematrix.skewY(angle) ⇒ <code>array</code>
398Returns a 4x4 matrix describing Y-axis shear.
399
400**Kind**: static method of <code>[Rematrix](#module_Rematrix)</code>
401
402| Param | Type | Description |
403| --- | --- | --- |
404| angle | <code>number</code> | Measured in degrees |
405
406<a name="module_Rematrix.translate"></a>
407
408<br>
409
410### Rematrix.translate(distanceX, [distanceY]) ⇒ <code>array</code>
411Returns a 4x4 matrix describing 2D translation. The first argument
412is used for both X and Y-axis translation, unless an optional
413second argument is provided to explicitly define Y-axis translation.
414
415**Kind**: static method of <code>[Rematrix](#module_Rematrix)</code>
416
417| Param | Type | Description |
418| --- | --- | --- |
419| distanceX | <code>number</code> | Measured in pixels. |
420| [distanceY] | <code>number</code> | Measured in pixels. |
421
422<a name="module_Rematrix.translateX"></a>
423
424<br>
425
426### Rematrix.translateX(distance) ⇒ <code>array</code>
427Returns a 4x4 matrix describing X-axis translation.
428
429**Kind**: static method of <code>[Rematrix](#module_Rematrix)</code>
430
431| Param | Type | Description |
432| --- | --- | --- |
433| distance | <code>number</code> | Measured in pixels. |
434
435<a name="module_Rematrix.translateY"></a>
436
437<br>
438
439### Rematrix.translateY(distance) ⇒ <code>array</code>
440Returns a 4x4 matrix describing Y-axis translation.
441
442**Kind**: static method of <code>[Rematrix](#module_Rematrix)</code>
443
444| Param | Type | Description |
445| --- | --- | --- |
446| distance | <code>number</code> | Measured in pixels. |
447
448<a name="module_Rematrix.translateZ"></a>
449
450<br>
451
452### Rematrix.translateZ(distance) ⇒ <code>array</code>
453Returns a 4x4 matrix describing Z-axis translation.
454
455**Kind**: static method of <code>[Rematrix](#module_Rematrix)</code>
456
457| Param | Type | Description |
458| --- | --- | --- |
459| distance | <code>number</code> | Measured in pixels. |