Price:

★حالة المنتج : جديد

★شحن مجاني جميع المحافظات

★ تم التحقق من المنتج بواسطة : نكست ستور

★لشراء المنتج من خلال زر الشراء

قراءة المزيد

Pixel Art Studio

Make your own single-div pixel art with CSS.

* { box-sizing: border-box; } body { --space: clamp(1rem, 2vw, 2.5rem); --shadow: 0.6rem 0.6rem 0; font-family: 'VT323', monospace; font-size: 1.2rem; margin: 0; padding: calc(var(--space) * 2) var(--space); background: lightblue; accent-color: turquoise; min-height: 100vh; display: flex; align-items: center; justify-content: center; } button { font-family: inherit; font-size: inherit; background: orchid; border: 0.22rem solid; border-radius: 0.3rem; padding: 0.2rem 1rem; box-shadow: 0.2rem 0.2rem 0; } button:hover, button:focus-visible { background: orange; } input[type="color"] { border: 0.22rem solid; border-radius: 0.3rem; box-shadow: 0.2rem 0.2rem 0; margin-right: 2rem; } h1 { font-family: 'Press Start 2P', cursive; font-weight: 400; margin: 0 0 var(--space); text-shadow: 0.1em 0.1em 0 orange; } p { margin: 0; } header { outline: 0.3rem solid; padding: var(--space); margin-bottom: calc(var(--space) * 2); box-shadow: var(--shadow); background: peachpuff; } .wrapper { width: 100%; max-width: 800px; margin: 0 auto; } @media (min-width: 70em) { .wrapper { max-width: 1200px; display: grid; grid-template-columns: 2fr 1fr; gap: 0 2rem; } } .controls { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; margin-bottom: calc(var(--space) * 1.5); grid-column: 1; } .canvas { --sizeX: var(--cellSizeCol, calc(100% / var(--colCount, 40))); --sizeY: var(--cellSizeRow, calc(100% / var(--rowCount, 30))); grid-column: 1; position: relative; outline: 0.3rem solid; box-shadow: var(--shadow); margin-bottom: calc(var(--space) * 2); background: linear-gradient(to right, transparent calc(100% - 1px), lightgrey 0), linear-gradient(to bottom, transparent calc(100% - 1px), lightgrey 0), white; background-size: var(--sizeX) 100%, 100% var(--sizeY); } .draw-area { position: relative; aspect-ratio: 4 / 3; background-repeat: no-repeat; background-size: var(--sizeX) var(--sizeY); } .marker { position: absolute; width: 100%; height: 100%; top: 0; left: 0; background-image: linear-gradient(to right, var(--bg, black), var(--bg, black)); aspect-ratio: 1; background-size: var(--sizeX) var(--sizeY); background-repeat: no-repeat; opacity: 0; } .css label { display: block; } textarea { display: block; width: 100%; border: 0.3rem 0.3rem 0; box-shadow: var(--shadow); margin-bottom: var(--space); padding: 0 1rem; } [data-undo] { background: orange; }const canvas = d3.select('.canvas') const colorInput = d3.select('#colorPicker') const marker = d3.select('.marker') const clearButton = d3.select('[data-clear]') const saveButton = d3.select('[data-save]') const undoButton = d3.select('[data-undo]') const copyButton = d3.select('[data-copy]') const textArea = d3.select('#css') const drawArea = d3.select('.draw-area') const range = d3.select('#columns') const width = drawArea.node().offsetWidth const height = drawArea.node().offsetHeight let columns = 30 const multiplier = height / width let rows = columns * multiplier let cellSize = 100 / columns let rowSize = 100 / rows let isPressed = false const bisect = d3.bisector((d) => d) const dx = (posX) => { const stepX = 1 / (columns - 1) const dataX = d3.range(0, 100, stepX) const indexX = bisect.center(dataX, posX / width) return (dataX[indexX] * 100).toFixed(2) } const dy = (posY) => { const stepY = 1 / (rows - 1) const dataY = d3.range(0, 1, stepY) const indexY = bisect.center(dataY, posY / height) return (dataY[indexY] * 100).toFixed(2) } let bg = [] let bgPosition = [] const draw = () => { drawArea .style('background-image', bg.join(',')) .style('background-position', bgPosition.join(',')) } const updateText = () => { textArea.html(` aspect-ratio: 4 / 3; background-image: ${bg.join(',')}; background-size: calc(100% / ${columns}) calc(100% / ${rows}); background-position: ${bgPosition.join(',')}; background-repeat: no-repeat; `) } const shouldDraw = (newBgValue, newBgPositionValue) => { if (!isPressed) return false if (!bg.length) return true if (bg[0] !== newBgValue) return true return bgPosition[0] !== newBgPositionValue } canvas.on('click', (e) => { const color = colorInput.node().value const [posX, posY] = d3.pointer(e) const x = dx(posX) const y = dy(posY) bg = [ `linear-gradient(${color}, ${color})`, ...bg ] bgPosition = [ `${x}% ${y}%`, ...bgPosition] draw() updateText() }) canvas .on('mouseover', () => { marker.style('opacity', 1) }) .on('mouseout', () => { marker.style('opacity', 0) }) .on('mousedown', () => { isPressed = true }) .on('mouseup', () => { isPressed = false }) canvas.on('mousemove', (e) => { const color = colorInput.node().value const [posX, posY] = d3.pointer(e) const x = dx(posX) const y = dy(posY) marker .style('background-position', `${x}% ${y}%`) const newBgValue = `linear-gradient(${color}, ${color})` const newBgPositionValue = `${x}% ${y}%` if (!shouldDraw(newBgValue, newBgPositionValue)) return bg = [ newBgValue, ...bg ] bgPosition = [ newBgPositionValue, ...bgPosition] draw() updateText() }) colorInput.on('input', () => { marker.style('--bg', colorInput.node().value) }) const clear = () => { bg = [] bgPosition = [] textArea.html('') drawArea .style('background-image', '') .style('background-position', '') .style('background-size', '') } clearButton.on('click', clear) saveButton.on('click', () => { const art = textArea.node().value localStorage.setItem('art', art) }) const restoreSavedArt = () => { const savedArt = localStorage.getItem('art') if (!savedArt) return drawArea.attr('style', savedArt) textArea.html(savedArt) } const setColumnCount = () => { columns = range.node().value rows = columns * multiplier cellSize = 100 / columns rowSize = 100 / rows canvas.style('--cellSizeCol', `${cellSize}%`) canvas.style('--cellSizeRow', `${rowSize}%`) canvas.style('--colCount', columns) } setColumnCount() restoreSavedArt() window.addEventListener('resize', () => { if (window.innerWidth > width + 100) return setColumnCount() }) range.on('input', setColumnCount) copyButton.on('click', (e) => { const copyText = textArea.node() copyText.select() copyText.setSelectionRange(0, 99999) navigator.clipboard.writeText(copyText.value) copyButton.text('Copied!') setTimeout(() => { copyButton.text('Copy to clipboard') }, 3000) }) undoButton.on('click', () => { bg.splice(0, 1) bgPosition.splice(0, 1) draw() updateText() })

0 Reviews