Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[gatsby-plugin-sharp] SVG traced placeholders #2456

Merged
merged 34 commits into from
Oct 20, 2017
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
96a236b
First shot at SVG „traced placeholders“
fk Oct 14, 2017
7d5756b
Merge branch 'master' into topics/2435-traced-placeholder
sebastienfi Oct 14, 2017
819de3f
Add fragments
fk Oct 14, 2017
00b69c0
Yo!
fk Oct 14, 2017
1c2fbc3
Memoize
fk Oct 14, 2017
ce59c9a
Support sizes()
fk Oct 14, 2017
8389ea3
Expose potrace options
fk Oct 14, 2017
795e02d
Add turnPolicy default
fk Oct 14, 2017
c214ea9
First shot at readme
fk Oct 15, 2017
beaa8bc
Add missing defaultValue „turnPolicy“
fk Oct 15, 2017
89f9d10
Remove invalid „;utf8“ param
fk Oct 15, 2017
da19d06
Remove default „trace“
fk Oct 15, 2017
6f050d0
Revert ‚Remove default „trace“’, fix default color of traced SVG
fk Oct 15, 2017
8b53888
D’oh
fk Oct 15, 2017
2e2fe51
Move require potrace/SVGO
fk Oct 15, 2017
8029eb6
Move „trace“ default values to type definition
fk Oct 15, 2017
4d294f3
Fix SVGs for IE
fk Oct 15, 2017
5be8a59
Fix potrace default options
fk Oct 17, 2017
c12f4e8
Add resolve function for „tracedSVG“
fk Oct 18, 2017
1e56b4c
D’oh :(
fk Oct 18, 2017
80e1bd5
Fix memoize, use image.src available in sizes and resolutions
fk Oct 18, 2017
fc334bc
Pass „trace“ args to „tracedSVG“ subfield
fk Oct 18, 2017
2029956
Brute-force fix things
fk Oct 19, 2017
ce8635b
Rename arg „trace“ -> „traceSVG“
fk Oct 19, 2017
74d77c0
READMEs
fk Oct 20, 2017
3cd3930
Minor README change
fk Oct 20, 2017
0778ee1
Add example page for tracedSVG
fk Oct 20, 2017
8e32e7b
Resize images before tracing the SVG
KyleAMathews Oct 20, 2017
53d7b4f
Temp copy fragments
KyleAMathews Oct 20, 2017
ff3c6b4
Make the default background color light gray
KyleAMathews Oct 20, 2017
750d702
Bring back trace args/defaults
fk Oct 20, 2017
ede2e3c
Demo color + background
fk Oct 20, 2017
c0fd0ca
Enable multipass, set float precision 🙏 @EmilTholin
fk Oct 20, 2017
eb5c7b9
Remove disclaimer from README
fk Oct 20, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 7 additions & 2 deletions examples/image-processing/src/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -306,14 +306,19 @@ export const pageQuery = graphql`
sizes: imageSharp(id: { regex: "/fecolormatrix-kanye-west.jpg/" }) {
sizes(
duotone: { highlight: "#f00e2e", shadow: "#192550" }
traceSVG: {
color: "#f00e2e"
turnPolicy: TURNPOLICY_MINORITY
blackOnWhite: false
}
toFormat: PNG
) {
...GatsbyImageSharpSizes
...GatsbyImageSharpSizes_tracedSVG
}
}
resolution: imageSharp(id: { regex: "/lol.jpg/" }) {
resolutions(grayscale: true, width: 500) {
...GatsbyImageSharpResolutions
...GatsbyImageSharpResolutions_tracedSVG
}
}
cropDefault: imageSharp(id: { regex: "/gatsby.jpg/" }) {
Expand Down
6 changes: 6 additions & 0 deletions examples/using-gatsby-image/src/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ class IndexComponent extends React.Component {
<li>
<Link to="/background-color/">Background color</Link>
</li>
<li>
<Link to="/traced-svg/">Traced SVG</Link>
</li>
</ul>
<h2>Out of the box it:</h2>
<ul>
Expand All @@ -73,6 +76,9 @@ class IndexComponent extends React.Component {
Uses the "blur-up" effect i.e. it loads a tiny version of the
image to show while the full image is loading
</li>
<li>
Alternatively provides a "traced placeholder" SVG of the image.
</li>
<li>
Lazy loads images which reduces bandwidth and speeds the initial
load time
Expand Down
117 changes: 117 additions & 0 deletions examples/using-gatsby-image/src/pages/traced-svg.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import React from "react"
import Img from "gatsby-image"

import { rhythm, options } from "../utils/typography"

const TracedSVG = ({ data }) => (
<div>
<h1>Viribus quid</h1>
<h2>Hippason sinu</h2>
<Img
style={{ display: `inherit` }}
css={{
marginBottom: rhythm(options.blockMarginBottom),
marginLeft: rhythm(options.blockMarginBottom),
float: `right`,
"&": {
"@media (min-width: 500px)": {
display: `none`,
},
},
}}
title={`Photo by Redd Angelo on Unsplash`}
resolutions={data.reddImageMobile.resolutions}
/>
<Img
style={{ display: `inherit` }}
css={{
marginBottom: rhythm(options.blockMarginBottom),
marginLeft: rhythm(options.blockMarginBottom),
float: `right`,
display: `none`,
"@media (min-width: 500px)": {
display: `inline-block`,
},
}}
title={`Photo by Redd Angelo on Unsplash`}
resolutions={data.reddImage.resolutions}
/>
<p>
Lorem markdownum nocens, est aut tergo, inmansuetique bella. Neve illud
contrarius ad es prior.{` `}
<a href="http://nunc.io/fuit.html">Planguntur</a> quondam, sua ferunt
uterum semina advertere si fraudesque terram hosti subiecta, nec. Audenti
refugitque manibusque aliis infelicem sed mihi aevis! Que ipso templa; tua
triformis animumque ad coluit in aliquid.
</p>
<ul>
<li>Infamia lumina sequuntur ulla</li>
<li>Aquarum rutilos</li>
<li>Hinc vimque</li>
</ul>
<h2>Et solebat pectus fletus erat furit officium</h2>
<p>
Proteus ut dis nec exsecrantia data: agrestes, truculenta Peleus. Et
diffidunt, talia intravit Thaumantias; figere et <em>et</em> qui socio
qui, <a href="http://vixmonet.io/in.html">tuo servet unda</a> hoc{` `}
<strong>classi</strong>? Causam <em>quemque</em>? Subigebant cornibus
fibras ut per nare nati, cunctis et <strong>illa verba</strong> inrita.
</p>
<ol>
<li>Furori adacto</li>
<li>Nocent imagine precari id ante sic</li>
<li>Ipsos sine Iuno placabitis silet relinquent blandarum</li>
<li>Et pars tabe sociorum et luna illum</li>
<li>Et frustra pestifero et inquit cornua victa</li>
<li>Constitit nomine senta suspirat et signis genuisse</li>
</ol>
<Img
sizes={data.kenImage.sizes}
title={`Photo by Ken Treloar on Unsplash`}
/>
<h2>Levia mihi</h2>
<p>
Precor Ortygiam, prudens diro stabant prodis moenia; aut tergo{` `}
<a href="http://orehaec.io/">loquax et data</a> sua rite in vulnere. Esse
lumina plaustrum lacus necopina, iam umbrae nec clipeo sentit{` `}
<a href="http://ut.org/hinc">sinistra</a>.
</p>
<p>
Pendebat nitidum vidistis ecce crematisregia fera et lucemque crines.{` `}
<a href="http://www.sub.net/">Est sopita satis</a> quod harena
Antimachumque tulit fusile. Fieri qui que prosit equidem, meis praescia
monebat cacumina tergo acerbo saepe nullaque.
</p>
</div>
)

export default TracedSVG

export const query = graphql`
query TracedSVGQuery {
reddImageMobile: imageSharp(id: { regex: "/redd/" }) {
resolutions(width: 125) {
...GatsbyImageSharpResolutions_tracedSVG
}
}
reddImage: imageSharp(id: { regex: "/redd/" }) {
resolutions(width: 200) {
...GatsbyImageSharpResolutions_tracedSVG
}
}
kenImage: imageSharp(id: { regex: "/ken-treloar/" }) {
sizes(
maxWidth: 600
traceSVG: {
turnPolicy: TURNPOLICY_MINORITY
blackOnWhite: true
turdSize: 100
threshold: 100
optTolerance: 1000
}
) {
...GatsbyImageSharpSizes_tracedSVG
}
}
}
`
12 changes: 8 additions & 4 deletions packages/gatsby-image/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ But creating optimized images for websites has long been a thorny problem. Ideal
* Generate multiple smaller images so smartphones and tablets don't download desktop-sized images
* Strip all unnecessary metadata and optimize JPEG and PNG compression
* Efficiently lazy load images to speed initial page load and save bandwidth
* Use the "blur-up" technique to show a preview of the image while it loads
* Use the "blur-up" technique or a "[traced placeholder](https://github.com/gatsbyjs/gatsby/issues/2435)" SVG to show a preview of the image while it loads
* Hold the image position so your page doesn't jump while images load

Doing this consistantly across a site feels like sisyphean labor. You manually optimize your images and then… several images are swapped in at the last minute or a design-tweak shaves 100px of width off your images.
Expand Down Expand Up @@ -94,8 +94,10 @@ Their fragments are:

* `GatsbyImageSharpResolutions`
* `GatsbyImageSharpResolutions_noBase64`
* `GatsbyImageSharpResolutions_tracedSVG`
* `GatsbyImageSharpSizes`
* `GatsbyImageSharpSizes_noBase64`
* `GatsbyImageSharpSizes_tracedSVG`

### gatsby-source-contentful

Expand All @@ -104,7 +106,9 @@ Their fragments are:
* `GatsbyContentfulSizes`
* `GatsbyContentfulSizes_noBase64`

If you don't want to use the blur-up effect, choose the fragment with `noBase64` at the end.
If you don't want to use the blur-up effect, choose the fragment with `noBase64` at the end. If you want to use the traced placeholder SVGs, choose the fragment with `tracedSVG` at the end.

_Please see the [gatsby-plugin-sharp](https://www.gatsbyjs.org/packages/gatsby-plugin-sharp/#tracedsvg) documentation for more information on `tracedSVG` and its configuration options._

## "Resolutions" queries

Expand All @@ -120,7 +124,7 @@ Pass in the data returned from the `resolutions` object in your query via the `r
# Other options include height (set both width and height to crop),
# grayscale, duotone, rotate, etc.
resolutions(width: 400) {
# Choose either the fragment including a small base64ed image or one without.
# Choose either the fragment including a small base64ed image, a traced placeholder SVG, or one without.
...GatsbyImageSharpResolutions
}
}
Expand All @@ -143,7 +147,7 @@ Pass in the data returned from the `sizes` object in your query via the `sizes`
# Other options include maxHeight (set both maxWidth and maxHeight to crop),
# grayscale, duotone, rotate, etc.
sizes(maxWidth: 700) {
# Choose either the fragment including a small base64ed image or one without.
# Choose either the fragment including a small base64ed image, a traced placeholder SVG, or one without.
...GatsbyImageSharpSizes_noBase64
}
}
Expand Down
22 changes: 22 additions & 0 deletions packages/gatsby-image/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,17 @@ class Image extends React.Component {
/>
)}

{/* Show the traced SVG image. */}
{image.tracedSVG && (
<Img
alt={alt}
title={title}
src={image.tracedSVG}
opacity={!this.state.imgLoaded ? 1 : 0}
transitionDelay={`0.25s`}
/>
)}

{/* Show a solid background color. */}
{bgColor && (
<div
Expand Down Expand Up @@ -271,6 +282,17 @@ class Image extends React.Component {
/>
)}

{/* Show the traced SVG image. */}
{image.tracedSVG && (
<Img
alt={alt}
title={title}
src={image.tracedSVG}
opacity={!this.state.imgLoaded ? 1 : 0}
transitionDelay={`0.25s`}
/>
)}

{/* Show a solid background color. */}
{bgColor && (
<div
Expand Down
46 changes: 46 additions & 0 deletions packages/gatsby-plugin-sharp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,46 @@ the source image colors will be converted to match a gradient color chosen based
on each pixel's [relative luminance][4].
Logic is borrowed from [react-duotone][5].

#### tracedSVG

Generates a traced SVG of the image (see [the original GitHub issue][9]) and
returns the SVG as "[optimized URL-encoded][10]" `data:` URI.
It it used in [gatsby-image](https://www.gatsbyjs.org/packages/gatsby-image/) to
provide an alternative to the default inline base64 placeholder image.

Uses [node-potrace][11] and [SVGO][12] under the hood.
Default settings for node-potrace:

```javascript
{
color: `lightgray`,
optTolerance: 0.4,
turdSize: 100,
turnPolicy: TURNPOLICY_MAJORITY,
}
```

All [node-potrace `Potrace` parameters][13] are exposed and can be set via the
`traceSVG` argument:

```javascript
responsiveResolution(
traceSVG: {
color: "#f00e2e"
turnPolicy: TURNPOLICY_MINORITY
blackOnWhite: false
}
) {
src
srcSet
tracedSVG
}
```

Heads up: `tracedSVG` currently traces the _original_ image source. Depending
on source image size and settings, please make sure that the generated SVG
is of reasonable size, especially when using it as a placeholder.

[1]: https://alistapart.com/article/finessing-fecolormatrix
[2]: http://blog.72lions.com/blog/2015/7/7/duotone-in-js
[3]: https://ines.io/blog/dynamic-duotone-svg-jade
Expand All @@ -171,3 +211,9 @@ Logic is borrowed from [react-duotone][5].
[6]: http://sharp.dimens.io/en/stable/api-resize/#crop
[7]: http://sharp.dimens.io/en/stable/api-operation/#rotate
[8]: http://sharp.dimens.io/en/stable/api-colour/#greyscale
[9]: https://github.com/gatsbyjs/gatsby/issues/2435
[10]: https://codepen.io/tigt/post/optimizing-svgs-in-data-uris
[11]: https://github.com/tooolbox/node-potrace
[12]: https://github.com/svg/svgo
[13]: https://github.com/tooolbox/node-potrace#parameters
[14]: https://github.com/oliver-moran/jimp
4 changes: 3 additions & 1 deletion packages/gatsby-plugin-sharp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
"imagemin": "^5.2.2",
"imagemin-pngquant": "^5.0.0",
"lodash": "^4.17.4",
"potrace": "^2.1.1",
"progress": "^1.1.8",
"sharp": "^0.17.3"
"sharp": "^0.17.3",
"svgo": "^0.7.2"
},
"devDependencies": {
"babel-cli": "^6.26.0",
Expand Down