JSFiddle - React, Tailwind, and code Playground
by Kanatantsin
HTML
<div class="sprite-generator" id="generator">
<h2 class="sprite-generator__title">Генератор спрайтов</h2>
<p>
Добавьте изображения и нажмите на кнопку «Сгенерировать спрайт»
</p>
<input type="file" multiple class="sprite-generator__upload">
<div class="images__added-count">Изображений в спрайте:
<span class="images__added-count-value">0</span>
</div>
<!-- <canvas id="canvas"></canvas> -->
<button class="sprite-generator__generate">Сгенерировать спрайт</button>
<div class="sprite-generator__result">
<div class="sprite-generator__preview">
<img alt="" class="sprite-generator__result-image">
</div>
<textarea class="sprite-generator__code" cols="30" rows="10" placeholder="Здесь будет ваш CSS" readonly></textarea>
</div>
</div>
CSS
body {
margin: 0;
font-family: Verdana;
}
.sprite-generator {
box-sizing: border-box;
padding: 10px;
}
.sprite-generator__result {
margin-top: 15px;
display: flex;
}
.images__added-count {
margin-top: 10px;
margin-bottom: 10px;
}
.sprite-generator__preview {
flex-grow: 1;
position: relative;
border: 1px solid #ccc;
}
.sprite-generator__result-image {
max-width: 100%;
}
.sprite-generator__code {
flex-grow: 1;
}
JavaScript
const prop = ( data, name ) => data.map( item => item[ name ] ),
summ = data => data.reduce(( total, value ) => total + value, 0 );
class SpriteGenerator {
constructor( container ) {
this.uploadButton = container.querySelector( '.sprite-generator__upload' );
this.submitButton = container.querySelector( '.sprite-generator__generate' );
this.imagesCountContainer = container.querySelector( '.images__added-count-value' );
this.codeContainer = container.querySelector( '.sprite-generator__code' );
this.imageElement = container.querySelector( '.sprite-generator__result-image' );
this.images = [];
this.imagesCount = 0;
this.registerEvents();
}
registerEvents() {
this.uploadButton.addEventListener('change', event => this.upload(event));
this.submitButton.addEventListener('click', () => this.genSprite( {margin: {top: 12, right: 0, bot: 0, left: 0} } ));
}
upload(e) {
const files = Array.from(e.currentTarget.files).filter(
file => /^image\//.test(file.type)
);
Promise.all(files.map(this.crtImage))
.then(images => {
images.forEach(image => URL.revokeObjectURL(image.el.src));
this.images = this.images.concat(images);
})
.catch(err => console.error(`${err}`));
}
crtImage(file) {
return new Promise((done, fail) => {
const img = document.createElement('img');
img.src = URL.createObjectURL(file);
img.addEventListener('load', event => done({ name: file.name.replace(/\.\w*$/, ''), el: event.currentTarget, width: event.currentTarget.width, height: event.currentTarget.height }));
img.addEventListener('error', error => fail(error.message));
});
}
genSprite( {margin} ) {
const canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
canvas.width = Math.max( ...prop(this.images, 'width') ) + margin.left;
canvas.height = summ( prop(this.images, 'height') ) + (this.images.length - 1) * margin.top;
...