Commit d52259a5 authored by Robin de Mourat's avatar Robin de Mourat
Browse files

add robin experiments

parent e263788e
.DS_Store
\ No newline at end of file
Expérimentation pour travailler sur les images blend modes en css.
Objectif: sortir des images possédant des filtres/blend modes qui peuvent être directement transmises à un imprimeur.
Références :
* mix-blend-mode : https://developer.mozilla.org/fr/docs/Web/CSS/mix-blend-mode
Questions présentation :
* optimiser en cachant les data urls ?
* que se passe-t-il quand on met un élément en multiply au-dessus ?
\ No newline at end of file
/* To define how the book look on the screen: */
@media screen {
body {
background-color: var(--color-background);
}
.pagedjs_pages {
display: flex;
width: calc(var(--pagedjs-pagebox-width) * 2);
flex: 0;
flex-wrap: wrap;
margin: 0 auto;
margin-bottom: 3em;
}
.pagedjs_page {
background-color: var(--color-paper);
box-shadow: 0 0 0 2px var(--color-pageBox);
margin: 0;
flex-shrink: 0;
flex-grow: 0;
margin-top: 10mm;
}
.pagedjs_first_page {
/* margin-left: var(--pagedjs-pagebox-width); */
}
.pagedjs_page > [class*="pagedjs_margin"] {
box-shadow: 0 0 0 1px var(--color-marginBox);
}
[class*="pagedjs_margin"] {
box-shadow: 0 0 0 1px inset orange;
}
/* uncomment for recto/verso book.
--------------------------------------------------- */
/* .pagedjs_pages {
flex-direction: column;
width: 100%;
}
.pagedjs_first_page {
margin-left: 0;
}
.pagedjs_page {
margin: 0 auto;
margin-top: 20mm;
} */
}
\ No newline at end of file
figure {
object-fit: cover;
background: red;
break-inside: avoid;
position: relative;
}
figure img {
display: block;
/* position: absolute; */
max-width: 100%;
/* max-height: 30vh; */
object-fit:cover;
/* height: calc(var(--pagedjs-height) - 200px); */
}
p {
background: white;
}
.normal {
mix-blend-mode: normal;
}
.multiply {
mix-blend-mode: multiply;
}
.screen {
mix-blend-mode: screen;
}
.overlay {
mix-blend-mode: overlay;
}
.darken {
mix-blend-mode: darken;
}
.lighten {
mix-blend-mode: lighten;
}
.color-dodge {
mix-blend-mode: color-dodge;
}
.color-burn {
mix-blend-mode: color-burn;
}
.hard-light {
mix-blend-mode: hard-light;
}
.soft-light {
mix-blend-mode: soft-light;
}
.difference {
mix-blend-mode: difference;
}
.exclusion {
mix-blend-mode: exclusion;
}
.hue {
mix-blend-mode: hue;
}
.saturation {
mix-blend-mode: saturation;
}
.color {
mix-blend-mode: color;
}
.luminosity {
mix-blend-mode: luminosity;
}
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
<script src="https://cdn.jsdelivr.net/npm/css-tree@1.1.2/dist/csstree.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.5.0-beta4/html2canvas.min.js"></script>
<script src="https://unpkg.com/pagedjs/dist/paged.polyfill.js"></script>
<script type="module" type="application/javascript" src="script.js"></script>
<script type="application/javascript" src="parseBlendModes.js"></script>
<!-- <script type="application/javascript" src="processImages.js"></script> -->
<link rel="stylesheet" href="css/interface.css">
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<figure>
<p>mix-blend-mode: normal;</p>
<div class="colored-rect"></div>
<img class="normal"
src="https://img-19.ccm2.net/uV_MR86--H0-ZK2MioHY7jYD07o=/1000x420/smart/b829396acc244fd484c5ddcdcb2b08f3/ccmcms-commentcamarche/20494859.jpg"
alt="image de test">
</figure>
<figure>
<p>mix-blend-mode: multiply;</p>
<img class="multiply"
src="https://img-19.ccm2.net/uV_MR86--H0-ZK2MioHY7jYD07o=/1000x420/smart/b829396acc244fd484c5ddcdcb2b08f3/ccmcms-commentcamarche/20494859.jpg"
alt="image de test">
</figure>
<figure>
<p>mix-blend-mode: screen;</p>
<img class="screen"
src="https://img-19.ccm2.net/uV_MR86--H0-ZK2MioHY7jYD07o=/1000x420/smart/b829396acc244fd484c5ddcdcb2b08f3/ccmcms-commentcamarche/20494859.jpg"
alt="image de test">
</figure>
<figure>
<p>mix-blend-mode: overlay;</p>
<img class="overlay"
src="https://img-19.ccm2.net/uV_MR86--H0-ZK2MioHY7jYD07o=/1000x420/smart/b829396acc244fd484c5ddcdcb2b08f3/ccmcms-commentcamarche/20494859.jpg"
alt="image de test">
</figure>
<figure>
<p>mix-blend-mode: darken;</p>
<img class="darken"
src="https://img-19.ccm2.net/uV_MR86--H0-ZK2MioHY7jYD07o=/1000x420/smart/b829396acc244fd484c5ddcdcb2b08f3/ccmcms-commentcamarche/20494859.jpg"
alt="image de test">
</figure>
<figure>
<p>mix-blend-mode: lighten;</p>
<img class="lighten"
src="https://img-19.ccm2.net/uV_MR86--H0-ZK2MioHY7jYD07o=/1000x420/smart/b829396acc244fd484c5ddcdcb2b08f3/ccmcms-commentcamarche/20494859.jpg"
alt="image de test">
</figure>
<figure>
<p>mix-blend-mode: color-dodge;</p>
<img class="color-dodge"
src="https://img-19.ccm2.net/uV_MR86--H0-ZK2MioHY7jYD07o=/1000x420/smart/b829396acc244fd484c5ddcdcb2b08f3/ccmcms-commentcamarche/20494859.jpg"
alt="image de test">
</figure>
<figure>
<p>mix-blend-mode: color-burn;</p>
<img class="color-burn"
src="https://img-19.ccm2.net/uV_MR86--H0-ZK2MioHY7jYD07o=/1000x420/smart/b829396acc244fd484c5ddcdcb2b08f3/ccmcms-commentcamarche/20494859.jpg"
alt="image de test">
</figure>
<figure>
<p>mix-blend-mode: hard-light;</p>
<img class="hard-light"
src="https://img-19.ccm2.net/uV_MR86--H0-ZK2MioHY7jYD07o=/1000x420/smart/b829396acc244fd484c5ddcdcb2b08f3/ccmcms-commentcamarche/20494859.jpg"
alt="image de test">
</figure>
<figure>
<p>mix-blend-mode: soft-light;</p>
<img class="soft-light"
src="https://img-19.ccm2.net/uV_MR86--H0-ZK2MioHY7jYD07o=/1000x420/smart/b829396acc244fd484c5ddcdcb2b08f3/ccmcms-commentcamarche/20494859.jpg"
alt="image de test">
</figure>
<figure>
<p>mix-blend-mode: difference;</p>
<img class="difference;"
src="https://img-19.ccm2.net/uV_MR86--H0-ZK2MioHY7jYD07o=/1000x420/smart/b829396acc244fd484c5ddcdcb2b08f3/ccmcms-commentcamarche/20494859.jpg"
alt="image de test">
</figure>
<figure>
<p>mix-blend-mode: exclusion;</p>
<img class="exclusion;"
src="https://img-19.ccm2.net/uV_MR86--H0-ZK2MioHY7jYD07o=/1000x420/smart/b829396acc244fd484c5ddcdcb2b08f3/ccmcms-commentcamarche/20494859.jpg"
alt="image de test">
</figure>
<figure>
<p>mix-blend-mode: hue;</p>
<img class="hue;"
src="https://img-19.ccm2.net/uV_MR86--H0-ZK2MioHY7jYD07o=/1000x420/smart/b829396acc244fd484c5ddcdcb2b08f3/ccmcms-commentcamarche/20494859.jpg"
alt="image de test">
</figure>
<figure>
<p>mix-blend-mode: saturation;</p>
<img class="saturation;"
src="https://img-19.ccm2.net/uV_MR86--H0-ZK2MioHY7jYD07o=/1000x420/smart/b829396acc244fd484c5ddcdcb2b08f3/ccmcms-commentcamarche/20494859.jpg"
alt="image de test">
</figure>
<figure>
<p>mix-blend-mode: color;</p>
<img class="color;"
src="https://img-19.ccm2.net/uV_MR86--H0-ZK2MioHY7jYD07o=/1000x420/smart/b829396acc244fd484c5ddcdcb2b08f3/ccmcms-commentcamarche/20494859.jpg"
alt="image de test">
</figure>
<figure>
<p>mix-blend-mode: luminosity;</p>
<img class="luminosity;"
src="https://img-19.ccm2.net/uV_MR86--H0-ZK2MioHY7jYD07o=/1000x420/smart/b829396acc244fd484c5ddcdcb2b08f3/ccmcms-commentcamarche/20494859.jpg"
alt="image de test">
</figure>
</body>
</html>
const replaceImage = (domImage, screenCanvas, transformFn) => {
return new Promise((resolve, reject) => {
const canvas = document.createElement('canvas');
let ctx = canvas.getContext("2d");
domImage.crossOrigin = "anonymous"; // This enables CORS
let isLoaded = false;
domImage.addEventListener('load', function() {
if (!isLoaded) {
const displayedWidth = domImage.getBoundingClientRect().width;
const displayedHeight = domImage.getBoundingClientRect().height;
canvas.width = displayedWidth;
canvas.height = displayedHeight;
if (typeof transformFn === 'function') {
ctx = transformFn(ctx, screenCanvas, domImage, displayedWidth, displayedHeight);
} else {
ctx.drawImage(domImage, 0, 0, displayedWidth, displayedHeight);
}
domImage.src = canvas.toDataURL();
resolve(domImage);
isLoaded = true;
}
})
domImage.addEventListener('error', reject);
})
}
const parseImages = (selector = 'img', transformFn) => {
const images = document.querySelectorAll(selector);
// console.log('images', selector, images)
return new Promise((resolve, reject) => {
html2canvas(document.body).then(function(canvas) {
Promise.all(
[...images].map(
img => replaceImage(img, canvas, transformFn)
)
)
.then(() => {
console.log(`toutes les images ${selector} ont été transformées`)
resolve();
})
.catch(reject)
})
})
}
const blackAndWhite = (ctx, image, displayedWidth, displayedHeight) => {
ctx.drawImage(image, 0, 0, displayedWidth, displayedHeight);
ctx.globalCompositeOperation='color';
ctx.fillStyle = "white";
ctx.globalAlpha = 1; // alpha 0 = no effect 1 = full effect
ctx.fillRect(0, 0, displayedWidth, displayedHeight);
return ctx;
}
const applyBlendMode = mode => (ctx, screenCanvas, image, displayedWidth, displayedHeight) => {
const prev = image.parentNode;
const background = window.getComputedStyle(prev, null).getPropertyValue('background-color');
ctx.globalCompositeOperation = 'source-over';
ctx.drawImage(image, 0, 0, displayedWidth, displayedHeight);
ctx.fillStyle = background;
ctx.globalCompositeOperation = mode;
ctx.fillRect(0, 0, displayedWidth, displayedHeight);
ctx.globalCompositeOperation = 'overlay';
ctx.drawImage(image, 0, 0, displayedWidth, displayedHeight);
// const imagePosition = image.getBoundingClientRect();
// ctx.globalCompositeOperation = 'source-over';
// // ctx.drawImage(image, 0, 0, displayedWidth, displayedHeight);
// ctx.drawImage(screenCanvas, imagePosition.x, imagePosition.y, displayedWidth, displayedHeight);
// ctx.globalCompositeOperation = mode;
// ctx.drawImage(screenCanvas, imagePosition.x, imagePosition.y, displayedWidth, displayedHeight);
// ctx.globalAlpha = .5;
// // ctx.globalCompositeOperation = "overlay";
// ctx.drawImage(image, 0, 0, displayedWidth, displayedHeight);
return ctx;
}
class MyHandler extends Paged.Handler {
constructor(chunker, polisher, caller) {
super(chunker, polisher, caller);
this.blendInstructions = new Map();
}
afterRendered(_pages) {
Array.from(this.blendInstructions).reduce((cur, [selector, mode]) => {
return cur.then(() => parseImages(selector, applyBlendMode(mode)))
}, Promise.resolve())
// parseImages(applyBlendMode('multiply'));
}
onDeclaration(declaration, dItem, dList, rule) {
if (declaration.property === "mix-blend-mode") {
let selector = csstree.generate(rule.ruleNode.prelude);
const val = declaration.value.children.first().name;
if (val !== 'normal') {
dList.remove(dItem);
this.blendInstructions.set(selector, val);
}
}
}
}
Paged.registerHandlers(MyHandler);
\ No newline at end of file
const replaceImage = (domImage, resolution = 300) => {
return new Promise((resolve, reject) => {
const canvas = document.createElement('canvas');
let ctx = canvas.getContext("2d");
domImage.crossOrigin = "anonymous"; // This enables CORS
let isLoaded = false;
domImage.addEventListener('load', function() {
if (!isLoaded) {
const displayedWidth = domImage.getBoundingClientRect().width;
const displayedHeight = domImage.getBoundingClientRect().height;
canvas.width = displayedWidth;
canvas.height = displayedHeight;
ctx.drawImage(domImage, 0, 0, displayedWidth, displayedHeight);
domImage.src = canvas.toDataURL();
resolve(domImage);
isLoaded = true;
}
})
domImage.addEventListener('error', reject);
})
}
const parseImages = (resolution) => {
const images = document.querySelectorAll('img');
Promise.all(
[...images].map(
img => replaceImage(img, resolution)
)
)
.then(() => {
console.log('toutes les images ont été transformées')
})
}
class MyHandler extends Paged.Handler {
constructor(chunker, polisher, caller) {
super(chunker, polisher, caller);
}
afterRendered(_pages) {
parseImages(300);
}
}
Paged.registerHandlers(MyHandler);
window.Paged.config = {
imagesResolution: 300
}
\ No newline at end of file
const replaceImage = (domImage, transformFn) => {
return new Promise((resolve, reject) => {
const canvas = document.createElement('canvas');
let ctx = canvas.getContext("2d");
domImage.crossOrigin = "anonymous"; // This enables CORS
domImage.addEventListener('load', function() {
const width = this.width;
const height = this.height;
canvas.width = width;
canvas.height = height;
if (typeof transformFn === 'function') {
ctx = transformFn(ctx, domImage, width, height);
} else {
ctx.drawImage(domImage, 0, 0, width, height, width, height);
}
domImage.src = canvas.toDataURL();
resolve(domImage);
})
domImage.addEventListener('error', reject);
})
}
const parseImages = (transformFn) => {
Promise.all([...document.querySelectorAll('img')].map(img => replaceImage(img, transformFn)))
}
const blackAndWhite = (ctx, image, width, height) => {
ctx.drawImage(image, 0, 0, width, height, 0, 0, width, height);
ctx.globalCompositeOperation='color';
ctx.fillStyle = "white";
ctx.globalAlpha = 1; // alpha 0 = no effect 1 = full effect
ctx.fillRect(0, 0, width, height);
return ctx;
}
parseImages(blackAndWhite);
\ No newline at end of file
# Float notes
a script proposal using float for notes.
\ No newline at end of file
/* To define how the book look on the screen: */
:root {
/* color for the interface */
--color-background: rgba(0, 0, 0, 0.2);
--color-marginBox: transparent;
--color-pageBox: transparent;
--color-paper: white;
/* color used for the baseline */
--pagedjs-baseline-color: cyan;
/* height of the baseline*/
--pagedjs-baseline: 8px;
}
@media screen {
body {
background-color: var(--color-background);
}
.pagedjs_pages {
display: flex;
width: calc(var(--pagedjs-width) * 2);
flex: 0;
flex-wrap: wrap;
margin: 0 auto;
margin-bottom: 3em;
}
.pagedjs_page {
background-color: var(--color-paper);
box-shadow: 0 0 0 2px var(--color-pageBox);
margin: 0;
flex-shrink: 0;
flex-grow: 0;
margin-top: 10mm;
}
.pagedjs_first_page {
margin-left: var(--pagedjs-width);
}
/* uncomment for recto/verso book.
--------------------------------------------------- */
/* .pagedjs_pages {
flex-direction: column;
width: 100%;
}
.pagedjs_first_page {
margin-left: 0;
}
.pagedjs_page {
margin: 0 auto;
margin-top: 10mm;
} */
/* uncomment for baseline
--------------------------------------------------- */
/* .pagedjs_page {
background: linear-gradient( white 0%, white calc(var(--pagedjs-baseline) - 1px), var(--pagedjs-baseline-color) calc(var(--pagedjs-baseline) - 1px), var(--pagedjs-baseline-color) var(--pagedjs-baseline)), transparent;
background-size: 100% var(--pagedjs-baseline);
background-repeat: repeat-y;
background-position-y: 0;
} */
}
\ No newline at end of file
:root{
--pagedjs_notes-area-page-left-width: 100%;
--pagedjs_notes-area-page-right-width: 100%;
--pagedjs_notes-area-page-left-maxHeight: 100%;
--pagedjs_notes-area-page-right-maxHeight: 100%;
}
.pagedjs_left_page .pagedjs_area-notes {
width: var(--pagedjs_notes-area-page-left-width);
max-height: var(--pagedjs_notes-area-page-left-maxHeight);
}
.pagedjs_right_page .pagedjs_area-notes {
width: var(--pagedjs_notes-area-page-right-width);
width: var(--pagedjs_notes-area-page-right-maxHeight);
}
.pagedjs_area-notes::before{
content: "---";
}
body {
counter-reset: pagedjsMarkerNote pagedjsCallNote;
}
.pagedjs_note{
display: block;
counter-increment: pagedjsMarkerNote;
}
.pagedjs_callnote{
counter-increment: pagedjsCallNote;
vertical-align:super;
}
.pagedjs_callnote::after{ content: counter(pagedjsCallNote); }
.pagedjs_note::before{ content: counter(pagedjsMarkerNote) ". ";}
/*
Proposal about specs (spread declared)
-------------------------------------
@page:left{
@note {
float: bottom left;
width: 150px;
}
}
@page:right{
@note {
float: bottom right;
width: 150px;
}
}
.sidenote{ float: note; }
Proposal about specs (spread declared)
-------------------------------------
@page{
@note {
float: bottom outside;
}
}
*/
\ No newline at end of file