react实现一个css边框图片生成器效果代码
代码语言:html
所属分类:布局界面
代码描述:react实现一个css边框图片生成器效果代码,可自己上传图片生成一个边框图片。
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/babel.min.js"></script> <style> @import url("https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap"); :root { --base-space: 8px; --color-body: #101820; --color-accent: #f9ea00; --color-main: #fafafa; } *, *::after, *::before { box-sizing: border-box; } body { background-color: var(--color-main); color: var(--color-body); margin: 0; padding: calc(var(--base-space) * 2); font-family: "Montserrat", sans-serif; font-weight: 400; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; font-size: calc(var(--base-space) * 2); } code { font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } p { margin-top: 0; } .display-block { display: block; } .txt-weight-bold { font-weight: 700; } .txt-size-2 { font-size: calc(var(--base-space) * 2); } .txt-size-3 { font-size: calc(var(--base-space) * 3); } .margin-bottom-1 { margin-bottom: var(--base-space); } .margin-bottom-2 { margin-bottom: calc(var(--base-space) * 2); } .margin-bottom-3 { margin-bottom: calc(var(--base-space) * 3); } .margin-bottom-4 { margin-bottom: calc(var(--base-space) * 3); } h1, h2 { margin-bottom: 0.35em; } h1 { font-size: calc(var(--base-space) * 6); font-weight: 700; } h2 { font-size: calc(var(--base-space) * 4); font-weight: 700; } h3 { font-size: calc(var(--base-space) * 2); font-weight: 700; } code { background-color: var(--color-main); display: block; padding: calc(var(--base-space) * 2); white-space: normal; } .App { background-color: white; box-shadow: 0px 3px 20px 0px rgba(0, 0, 0, 0.15); border-radius: calc(var(--base-space) * 2); margin: 0 auto; padding: calc(var(--base-space) * 4); display: flex; flex-wrap: wrap; gap: calc(var(--base-space) * 4); } .App__title { text-align: center; flex: 0 0 100%; } .App__column { flex: 1 1 45%; } .Section { margin-bottom: calc(var(--base-space) * 5); } .HandlersWrapper { position: relative; display: table; } .DemoList { display: flex; gap: calc(var(--base-space) * 2); } .DemoList__button { -webkit-appearance: none; -moz-appearance: none; appearance: none; background: none; border: none; padding: 0; } .DemoList__item { flex: 0 1 80px; } .DemoList__thumbnail { display: block; width: 100%; } .DemoText { font-size: 2em; text-align: center; padding: 0.25em; } </style> </head> <body> <div id="app"></div> <script type="module"> import React, { useEffect, useRef, useState } from "https://cdn.skypack.dev/react"; import ReactDOM from "https://cdn.skypack.dev/react-dom"; import { Rnd } from "https://cdn.skypack.dev/react-rnd"; const getImageFromInput = function (input) { if (!input) return; return new Promise((resolve, reject) => { const file = new FileReader(); const img = new Image(); file.onloadend = fileData => { img.onload = () => { resolve(img); }; img.src = fileData.target.result; }; img.onerror = reject; file.onerror = reject; file.readAsDataURL(input); }); }; const HANDLER_STYLE = { display: "flex", alignItems: "center", justifyContent: "center", background: "rgba(0,0,0,0.3)", border: "solid 1px black", opacity: 0.7 }; const Handler = function ({ position, size, onPositionChange, onSizeChange, style = {}, children }) { const handlePositionChange = (e, d) => { if (onPositionChange) onPositionChange({ x: Math.round(d.x), y: Math.round(d.y) }); }; const handleSizeChange = (e, direction, ref, delta, position) => { if (onSizeChange) onSizeChange({ ...position, // keeping it all numbers for consistency width: Math.round(parseInt(ref.style.width)), height: Math.round(parseInt(ref.style.height)) }); }; return /*#__PURE__*/( React.createElement(Rnd, { style: { ...HANDLER_STYLE, ...style }, bounds: "parent", size: { width: size.width, height: size.height }, position: { x: position.x, y: position.y }, onDragStop: handlePositionChange, onResizeStop: handleSizeChange }, children)); }; // I am using the colors from MDN's docs // https://developer.mozilla.org/en-US/docs/Web/CSS/border-image-slice // Easier to debug things const REGIONS_COLORS = [ "#E6F2F9", "#C7DDA8", "#FFFCAB", "#FCE5C9", "#D7D7D7", "#D7D7D7", "#D7D7D7", "#D7D7D7"]; const DEMO_IMAGES = [ "//repo.bfw.wiki/bfwrepo/images/beijing/pencil-1302150_960_720.png", "//repo.bfw.wiki/bfwrepo/images/beijing/angular-156626_960_720.png", "//repo.bfw.wiki/bfwrepo/images/beijing/art-deco-frame-4940087_960_720.png", "//repo.bfw.wiki/bfwrepo/images/beijing/frame-5890068_960_720.png", "//repo.bfw.wiki/bfwrepo/images/beijing/frame-5537777_960_720.png"]; // Using regular english names instead of region numbers // helped visualize and build a mental model const TOP_LEFT = 0; const TOP_RIGHT = 1; const BOTTOM_RIGHT = 2; const BOTTOM_LEFT = 3; const TOP_MIDDLE = 4; const MIDDLE_RIGHT = 5; const BOTTOM_MIDDLE = 6; const MIDDLE_LEFT = 7; const App = function () { const [isDraggingOver, setIsDraggingOver] = useState(false); const [handlers, setHandlers] = useState([]); const [output, setOutput] = useState(); const sourceCanvasRef = useRef(); const outputCanvasRef = useRef(); const initializeHandlers = (img, cb) => { const width = img.naturalWidth; const height = img.naturalHeight; const canvas = sourceCanvasRef.current; const ctx = canvas.getContext("2d"); // clear first with the current dimensions ctx.clearRect(0, 0, canvas.width, canvas.height); canvas.width = width; canvas.height = height; ctx.drawImage(img, 0, 0); const halfWidth = width / 2; const halfHeight = height / 2; const handlerWidth = Math.round(width * 0.25); const handlerHeight = Math.round(height * 0.25); const halfHandlerWidth = handlerWidth / 2; const halfHandlerHeight = handlerHeight / 2; const handlerDefaults = { width: handlerWidth, height: handlerHeight, x: 0, y: 0 }; // I am sure there is a smarter way of doing this // but this is easier to visualize const newHandlers = []; newHandlers[TOP_LEFT] = { ...handlerDefaults }; newHandlers[TOP_MIDDLE] = { ...handlerDefaults, x: halfWidth - halfHandlerWidth }; newHandlers[TOP_RIGHT] = { ...handlerDefaults, x: width - handlerWidth }; newHandlers[MIDDLE_RIGHT] = { ...handlerDefaults, x: width - handlerWidth, y: halfHeight - halfHandlerHeight }; newHandlers[MIDDLE_LEFT] = { ...handlerDefaults, y: halfHeight - halfHandlerHeight }; newHandlers[BOTTOM_LEFT] = { ...handlerDefaults, y: height - handlerHeight }; newHandlers[BOTTOM_MIDDLE] = { ...handlerDefaults, x: halfWidth - halfHandlerWidth, y: height - handlerHeight }; newHandlers[BOTTOM_RIGHT] = { ...handlerDefaults, x: width - handlerWidth, y: height - handlerHeight }; setHandlers(newHandlers); if (cb) cb(newHandlers); }; const readFromInput = async input => { if (!input) return; const img = await getImageFromInput(input); initializeHandlers(img); }; const readFromDemo = (event, cb) => { const demoIndex = event.currentTarget.dataset.index; const img = new Image(); img.crossOrigin = "Anonymous"; img.onload = () => { initializeHandlers(img, cb); }; img.onerror = err => { console.log(err.message); }; img.src = DEMO_IMAGES[demoIndex]; }; // Drag and drop const onDrop = event => { event.preventDefault(); event.dataTransfer.dropEffect = "copy"; readFromInput(event.dataTransfer.files[0]); setIsDraggingOver(false); }; const onInputChange = event => { readFromInput(event.target.files[0]); }; const onDragOver = event => { event.preventDefault(); event.dataTransfer.dropEffect = "copy"; setIsDraggingOver(true); }; const handleHandlerChange = (index, value) => { let updatedRegions = {}; updatedRegions[index] = { ...value }; // there is definitely a smarter way of doing this // but this was easier for me to visualize the regions // and the changes that each would have to make to one another const { width, height } = value; if (width || height) { if (index === TOP_LEFT) { // top sections share same height updatedRegions[TOP_RIGHT] = { height }; // top-left and bottom-left share the same width updatedRegions[BOTTOM_LEFT] = { width }; // middle sections can't be taller/wider than their counterpart regions updatedRegions[TOP_MIDDLE] = { height: Math.min(handlers[TOP_MIDDLE].height, height) }; updatedRegions[MIDDLE_LEFT] = { width: Math.min(handlers[MIDDLE_LEFT].width, width) }; } else if (index === TOP_RIGHT) { // top sections share same height updatedRegions[TOP_LEFT] = { height }; // top-right and bottom-right share the same width updatedRegions[BOTTOM_RIGHT] = { width }; // middle sections can't be taller/wider than their counterpart regions updatedRegions[TOP_MIDDLE] = { height: Math.min(handlers[TOP_MIDDLE].height, height) }; updatedRegions[MIDDLE_RIGHT] = { width: Math.min(handlers[MIDDLE_RIGHT].width, width) }; } else if (index === BOTTOM_LEFT) { // bottom-left and top-left share the same width updatedRegions[TOP_LEFT] = { width }; // bottom sections share same height updatedRegions[BOTTOM_RIGHT] = { height }; // middle sections can't be taller/wider than their counterpart regions updatedRegions[BOTTOM_MIDDLE] = { height: Math.min(handlers[BOTTOM_MIDDLE].height, height) }; updatedRegions[MIDDLE_LEFT] = { width: Math.min(handlers[MIDDLE_LEFT].width, width) }; } else if (index === BOTTOM_RIGHT) { // bottom-right and top-right share the same width updatedRegions[TOP_RIGHT] = { width }; // bottom sections share same height updatedRegions[BOTTOM_LEFT] = { height }; // middle sections can't be taller/wider than their counterpart regions updatedRegions[BOTTOM_MIDDLE] = { height: Math.min(handlers[BOTTOM_MIDDLE].height, height) }; updatedRegions[MIDDLE_RIGHT] = { width: Math.min(handlers[MIDDLE_RIGHT].width, width) }; } else if (index === TOP_MIDDLE) { // top-middle and bottom-middle share the same width updatedRegions[BOTTOM_MIDDLE] = { width }; // middle sections can't be taller than their regions counterparts updatedRegions[index].height = Math.min( height, handlers[TOP_LEFT].height); } else if (index === BOTTOM_MIDDLE) { // bottom-middle and top-middle share the same width upd.........完整代码请登录后点击上方下载按钮下载查看
网友评论0