The cause of
As a front-end engineer, daily development is inseparable from PSD files.
But a small popup page in daily development requires 30+Mb of PSD, so you have to clean the PSD regularly…
For me, PSD is just for measuring element size (element spacing), viewing attributes and other simple functions.
Think, compare
Compared with Sketch, Sketch has sketch-measure, which allows designers to export static resources to the front-end.
For PSD, there is already pxCook/Lanhuapp on the market, and the experience is also very good, but you need to download the (huge) PSD provided by U to mark the experience.
And sometimes we still need U to give us a (huge) PSD file so that we can automatically mark in Pxcook/Lanhuapp.
Therefore, in view of the above, we consider doing an open source project, similar to Sketch-Measure, which is positioned as PSD-Measure.
Results show
DEMO
The source code
The command line
We can also export page annotations using the command line
bash
NPM I measure-export-cli -g # PSD measure-export start path/to/psdDir # Build PSD file from 'path/to/psdDir' to 'dist' measure-export build path/to/psdDirCopy the code
Chrome plug-ins
The Chrome plugin is provided to pop up Measure UI when we click the PSD link instead of downloading the PSD. Of course, we can also click the download in the upper right to download it.
The installation
- To download the extension, click Download
- Open the Chrome extension page: Chrome :// Extensions /
- Drag and drop the downloaded package to the page to install it
- If this icon is displayed, the installation is complete
Design and Implementation
The process is as follows:
This section describes the PSD file format
- File Header (fixed length) contains the overall data of the PSD File, such as version, size, number of image channels, color category used (RGB, CMYK…).
- The Color Mode Data Section is mainly used for part of the Color type images
- Place some external Image Resources
- Layer and Mask put all kinds of information about the Layer and Mask, size position, font, stroke, etc
- Image Data (variable length) Puts Image pixel Data
PSD.js
Using psD.js, you parse the above file structure to get a readable data structure. Psd.js uses the getter to get lazy-parsed data:
const obj = Object.defineProperty({}, 'someParsedVal', { get: function () { if (! this._someParsedVal) { const afterMs = Date.now() + 3000 while (true) { if (Date.now() >= afterMs) { this._someParsedVal = 'ok' break}}} return this._someparsedVal}}) obj.someparsedVal // 3s after obj.someparsedval // soonCopy the code
There is a similar design in Mobx3 (LazyInitializer)
psd-html
PSD is parsed to HAST and converted to HTML
HAST (HTML Abstract Syntax tree)
The following HTML:
<a href="http://alpha.com" class="bravo" download></a>Copy the code
Corresponding HAST for
{
"type": "element",
"tagName": "a",
"properties": {
"href": "http://alpha.com",
"id": "bravo",
"className": ["bravo"],
"download": true
},
"children": []
}Copy the code
The front and back ends are isomorphic
Isomorphism means running on both the client and server, specifically in the browser and NodeJS environment
Some common ways to implement front and back isomorphism are to package js for different environments separately with the help of the build tools Browserify/rollup/WebPack
Simulation environment
- Nodejs built-in modules are not packaged in a NodeJS environment
- In the Browser environment, the default built-in modules are packaged, along with some global variables (e.g
process.env / __dirname
) also mock
Use variable substitution + Treeshake to differentiate between code in different environments
-
For example, WebPack configuration DefinePlugin
{ plugins: [ new webpack.DefinePlugin({ 'process.env.RUN_ENV': JSON.stringify('browser') }) ] } Copy the code
-
Differentiate between different environment packaging in your code
module.exports = process.env.RUN_ENV === 'browser' ? { psdToHtml, psdToHtmlFromBuffer, psdToHtmlFromURL, psdToHAST, psdToHASTFromBuffer } : { psdToHtml, psdToHtmlFromPath, psdToHtmlFromBuffer, psdToHAST, psdToHASTFromBuffer, psdToHASTFromPath }Copy the code
-
The js package will remove the psdToHASTFromPath code
package.json
configuration
As follows:
{
"main": "dist/psd-html.cjs.js",
"browser": "dist/psd-html.browser.cjs.js",
"cdn": "dist/psd-html.browser.umd.min.js",
"unpkg": "dist/psd-html.browser.umd.min.js"
}Copy the code
main
: nodejs Js loaded by the environmentbrowser
: js loaded by the browser environmentcdn
: Js loaded by some CDN servicesunpkg
: JS loaded by UNPkg CDN service (mainly packaged using UMD specification)
Visit unpkg.com/moyuyc/psd… Unpkg.com/moyuyc/psd…
HTML – measure interaction
Layout of the positioning
The PSD is exported as an entire image, automatically annotated using the positioning and size of each layer.
other
Two divs, relative to the absolute location of the same parent, how to determine whether they intersect?
.
It’s hard to make a straight heads judgment, because you have to think about all the different scenarios, and you have to think about the reverse, the disjoint scenarios. Now it’s easy
Disjoint as long as it satisfies one of the following four conditions
function isIntersect(node1, node2) { const rect1 = node1.getBoundingClientRect() const rect2 = node2.getBoundingClientRect() return ! ( rect1.right < rect2.left || rect1.left > rect2.right || rect1.bottom < rect2.top || rect1.top > rect2.bottom ) }Copy the code
measure-export(-cli)
Enter PSD/HTML to export the MEAS-UI static resources, as shown in the following figure (distinguish between prod and DEV environments)
Todo
- Render measurement UI when PSD is open in the browser
Related projects
- @moyuyc/psd.js – Parse PSD file, format (Forked from psd.js)
- @moyuyc/psd-html – psd -> hast -> html
- Html-measure – Annotate interaction
- Meas – UI – Front end UI display, including annotation interaction
- measure-export(-cli)- Enter PSD/HTML export
meas-ui
Static resource
The resources
- Adobe Photoshop File Formats Specification
- Photoshop Styles File Format
- JS. How to determine whether two rectangles intersect
- HAST