canvas离线画板画图

在线效果地址

离线画板画图

画板代码

<html>

<head>
    <title>You are not connected to the Internet</title>
    <meta property="og:url" content="https://dev.to/offline.html">
    <meta property="og:title" content="Looks like you've lost your Internet connection">
    <meta property="og:image" content="https://thepracticaldev.s3.amazonaws.com/i/aio6nc08tpcqavej512d.png">
    <meta property="og:description" content="Maybe you could go outside and get some fresh air.">
    <meta property="og:site_name" content="The DEV Community">

    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:site" content="@ThePracticalDev">
    <meta name="twitter:title" content="Looks like you've lost your Internet connection">
    <meta name="twitter:description" content="Maybe you could go outside and get some fresh air.">
    <meta name="twitter:image:src" content="https://thepracticaldev.s3.amazonaws.com/i/aio6nc08tpcqavej512d.png">

    <style>
        html,
        body,
        canvas {
            height: 100%;
            width: 100%;
            margin: 0;
            font-family: Helvetica;
            user-select: none;
        }

        body {
            display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: column;
            color: #444444;
        }

        h2,
        h3 {
            font-weight: 400;
        }

        h2 {
            font-size: 2em;
        }

        h3 {
            font-size: 1.3em;
        }

        canvas {
            position: fixed;
            top: 0;
            width: 100%;
            height: 100vh;
        }

        path {
            opacity: 50%;
        }

        .content {
            text-align: center;
            margin: 20px 20px;
        }

        .paletteSelector {
            z-index: 2;
            margin-top: 30px;
        }

        .colors {
            z-index: 2;
            margin: 0 20px;
            text-align: center;
        }

        .color {
            height: 50px;
            width: 50px;
            margin-right: 10px;
            border-radius: 50%;
            border: none;
        }

        .color:hover {
            opacity: .7;
            cursor: pointer;
        }

        .color:focus {
            outline: 0;
        }

        .rainbow-logo {
            border-radius: 10%;
            max-width: 40%;
            max-height: 400px;
        }

        .signature {
            margin-top: 20px;
        }

        #footer-container {
            display: none;
        }

        @media only screen and (max-height: 700px) {
            h2 {
                font-size: 1.5em;
            }

            h3 {
                font-size: 1.0em;
            }

            .color {
                height: 30px;
                width: 30px;
            }

            .signature {
                margin-top: 10px;
                margin-bottom: 10px;
            }

            .content {
                margin-bottom: 10px;
            }
        }
    </style>
</head>

<body>
    <canvas width="1920" height="213"></canvas>
    <div class="content">
        <svg viewBox="0 0 235 234" version="1.1" xmlns="http://www.w3.org/2000/svg"
            xmlns:xlink="http://www.w3.org/1999/xlink" class="rainbow-logo" preserveAspectRatio="xMinYMin meet">
            <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
                <g id="80K">
                    <polygon id="Shape" fill="#88AEDC" points="234.04 175.67 158.35 233.95 205.53 233.95 234.04 212">
                    </polygon>
                    <polygon id="Shape" points="234.04 140.06 112.11 233.95 112.13 233.95 234.04 140.08"></polygon>
                    <polygon id="Shape" points="133.25 0.95 0.04 103.51 0.04 103.53 133.27 0.95"></polygon>
                    <polygon id="Shape" fill="#F58F8E" fill-rule="nonzero" points="0.04 0.95 0.04 31.11 39.21 0.95">
                    </polygon>
                    <polygon id="Shape" fill="#FEE18A" fill-rule="nonzero"
                        points="39.21 0.95 0.04 31.11 0.04 67.01 85.84 0.95"></polygon>
                    <polygon id="Shape" fill="#F3F095" fill-rule="nonzero"
                        points="85.84 0.95 0.04 67.01 0.04 103.51 133.25 0.95"></polygon>
                    <polygon id="Shape" fill="#55C1AE" fill-rule="nonzero"
                        points="133.27 0.95 0.04 103.53 0.04 139.12 179.49 0.95"></polygon>
                    <polygon id="Shape" fill="#F7B3CE" fill-rule="nonzero"
                        points="234.04 0.95 226.67 0.95 0.04 175.45 0.04 211.38 234.04 31.2"></polygon>
                    <polygon id="Shape" fill="#88AEDC" fill-rule="nonzero"
                        points="179.49 0.95 0.04 139.12 0.04 175.45 226.67 0.95"></polygon>
                    <polygon id="Shape" fill="#F58F8E" fill-rule="nonzero"
                        points="234.04 31.2 0.04 211.38 0.04 233.95 18.07 233.95 234.04 67.65"></polygon>
                    <polygon id="Shape" fill="#FEE18A" fill-rule="nonzero"
                        points="234.04 67.65 18.07 233.95 64.7 233.95 234.04 103.56"></polygon>
                    <polygon id="Shape" fill="#F3F095" fill-rule="nonzero"
                        points="234.04 103.56 64.7 233.95 112.11 233.95 234.04 140.06"></polygon>
                    <polygon id="Shape" fill="#55C1AE" fill-rule="nonzero"
                        points="234.04 140.08 112.13 233.95 158.35 233.95 234.04 175.67"></polygon>
                    <polygon id="Shape" fill="#F7B3CE" fill-rule="nonzero"
                        points="234.04 212 205.53 233.95 234.04 233.95"></polygon>
                    <g id="Group" transform="translate(37.000000, 77.000000)" fill="#FFFFFF">
                        <path
                            d="M28.2371517,0.75 C32.7510836,1.7 36.0111455,3.55 39.371517,7.05 C42.4309598,10.25 44.3368421,13.9 45.1393189,18 C45.7913313,21.45 45.7913313,58.55 45.1393189,62.05 C43.4340557,71.15 35.6600619,78.25 26.0303406,79.5 C24.0241486,79.75 17.3034056,80 11.1845201,80 L-7.10542736e-15,80 L-7.10542736e-15,1.42108547e-14 L12.4383901,1.42108547e-14 C21.2656347,1.42108547e-14 25.7795666,0.2 28.2371517,0.75 Z M14.5448916,40 L14.5448916,65.6 L19.7108359,65.4 C24.174613,65.25 25.1275542,65.05 27.1337461,63.9 C31.0458204,61.6 31.0959752,61.45 31.0959752,39.7 C31.0959752,18.5 31.0959752,18.5 27.4346749,16.1 C25.6291022,14.9 24.8767802,14.75 19.9616099,14.55 L14.5448916,14.4 L14.5448916,40 Z"
                            id="Combined-Shape"></path>
                        <path
                            d="M93.7894737,7.25 L93.7894737,14.5 L68.2105263,14.5 L68.2105263,32.5 L83.7585139,32.5 L83.7585139,47 L68.2105263,47 L68.3108359,56.1 L68.4613003,65.25 L81.1504644,65.4 L93.7894737,65.5 L93.7894737,80 L78.993808,80 C62.5430341,80 59.9851393,79.7 57.3770898,77.4 C53.7157895,74.2 53.9164087,76.25 53.7659443,41.1 C53.6656347,19.2 53.8160991,8.85 54.1671827,7.45 C54.8693498,4.85 57.828483,1.65 60.4365325,0.75 C61.9913313,0.2 65.9034056,0.05 78.1411765,4.26325641e-14 L93.7894737,4.26325641e-14 L93.7894737,7.25 Z"
                            id="Path"></path>
                        <path
                            d="M125.437152,28.1 C129.148607,42.35 132.258204,53.7 132.358514,53.35 C132.508978,53 135.668731,40.95 139.430341,26.5 L146.301548,0.25 L154.125697,0.1 C160.043963,7.10542736e-15 162,0.15 162,0.6 C162,1.05 144.64644,66.8 143.643344,70.1 C142.941176,72.4 139.179567,77.1 137.073065,78.35 C134.414861,79.85 130.502786,80.1 128.095356,78.85 C125.9387,77.75 123.079876,74.45 121.625387,71.35 C120.722601,69.45 105.97709,15.35 102.566563,1.35 L102.21548,0 L110.039628,0 C117.713313,0 117.913932,0 118.31517,1.1 C118.515789,1.75 121.725697,13.9 125.437152,28.1 Z"
                            id="Path"></path>
                    </g>
                </g>
            </g>
        </svg>
        <h2> So, there's good news and bad news</h2>
        <h3>Bad news: It looks like you're offline</h3>
        <h3>Good news: You can draw a picture anywhere on this page while you wait to get it back!</h3>
        <h4>(pick a color below &amp;&amp; start drawing!)</h4>
    </div>

    <div class="colors" style="pointer-events: all;"><button class="color"
            style="background-color: rgb(244, 144, 142);"></button><button class="color"
            style="background-color: rgb(242, 240, 151);"></button><button class="color"
            style="background-color: rgb(136, 176, 220);"></button><button class="color"
            style="background-color: rgb(247, 181, 209);"></button><button class="color"
            style="background-color: rgb(83, 196, 175);"></button><button class="color"
            style="background-color: rgb(253, 227, 140);"></button></div>
    <div class="paletteSelector" style="pointer-events: all;">
        <!-- TODO: Populate options from javascript instead of hardcoding -->
        <select>
            <option value="default">Default Palette</option>
            <option value="paulTol">Paul Tol Palette</option>
        </select>
    </div>
    <svg width="75px" height="75px" viewBox="0 0 266 286" version="1.1" xmlns="http://www.w3.org/2000/svg"
        xmlns:xlink="http://www.w3.org/1999/xlink" class="signature">
        <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
            <g id="Artboard-3" transform="translate(-66.000000, -39.000000)" stroke="#F4908E" stroke-width="8">
                <g id="Group" transform="translate(70.000000, 44.000000)">
                    <path
                        d="M137.947881,11.0969119 C120.236214,10.7929621 127.259584,-4.63518682 110.600707,1.39809583 C98.4900537,5.78416547 5.38963223,31.9682026 1.99251552,84.34539 C0.138615017,112.929069 -0.563473858,141.639852 0.495802997,170.264134 C0.973626724,183.176113 16.3154795,204.585393 22.2134768,211.816457 C35.0843735,227.596436 61.6452079,206.201192 70.9197071,196.000824 C104.380023,159.200179 133.244668,118.47588 137.947881,67.1534449 C138.600896,60.027607 145.952931,5.41350351 126.011684,11.0969119 C112.376346,14.9830876 103.436568,65.3726702 102.950719,78.3517738 C101.357143,120.922959 86.4228272,211.00328 146.955431,222.813291 C172.852291,227.865812 169.286943,226.931981 192,226.931981"
                        id="Path-2"></path>
                    <path
                        d="M80,277.169785 C120.408772,252.192233 121.434199,237.685468 133.304963,222.650446 C151.591469,199.489509 173.572805,172.509583 233.39048,84.1055622 C240.794147,73.1637472 242.286005,30.9559106 238.678367,28.2608272 C236.630233,26.7307705 219.030597,13.826187 211.887732,18.9306581 C202.734845,25.4715418 203.241886,57.600262 203.223682,60.0372493 C203.010014,88.6406571 203.914879,117.248834 205.052575,145.830265 C206.126657,172.81357 211.080162,198.940616 208.995298,226.072378 C206.84232,254.090552 155.519583,271.514023 133.304963,268.076421 C126.954422,267.093706 93.5574761,243.825981 102.987596,240.93683 C113.776095,237.631506 146.615548,245.587641 160.390474,240.93683 C174.165399,236.286019 182.361602,234.057591 192.833448,229.336442 C203.454817,224.547881 249.685075,198.800486 259.8975,193.187538"
                        id="Path-3"></path>
                </g>
            </g>
        </g>
    </svg>
    <script type="text/javascript">

        const palettes = {
            default: ["#F4908E", "#F2F097", "#88B0DC", "#F7B5D1", "#53C4AF", "#FDE38C"],
            // Color-deficient accessible palettes: https://owi.usgs.gov/blog/tolcolors/
            paulTol: ["#B997C6", "#824D99", "#4E79C4", "#57A2AC", "#7EB875", "#D0B440", "#E67F33"],
            // Add more palette options below and to the "select" dropdown.
        }
        let activePalette = 'default' // match key inside the palettes variable

        // Globally DOM nodes + variables
        const paletteSelector = document.querySelector(".paletteSelector")
        const colorSelector = document.querySelector(".colors")
        const canvas = document.querySelector('canvas')
        const context = canvas.getContext('2d')
        const colorDiv = document.querySelector(".colors")
        let dx = 1, dy = 1;

        // handler for color input buttons
        function handleButtonClick(event) {
            const buttonStyle = event.target.style
            context.strokeStyle = buttonStyle.backgroundColor
        }

        // Main drawing function
        function renderColorButtons(colors) {
            // First, remove existing event listeners to prevent memory leak
            colorDiv.querySelectorAll('button').forEach((button) => {
                button.removeEventListener('click', handleButtonClick)
            })
            // Then, remove existing buttons
            colorDiv.innerHTML = ""

            // Lastly, add new a new button for each color in the passed in palette
            colors.forEach(color => {
                const button = document.createElement("button")
                button.classList.add("color")
                button.style.backgroundColor = color
                colorDiv.appendChild(button)
                button.addEventListener('click', handleButtonClick)
            })
        }

        // Helper for modifying canvas context
        const setContextSettings = (strokeColor) => {
            context.strokeStyle = strokeColor
            context.lineJoin = "round"
            context.lineWidth = 5
        }

        const setCanvasSize = () => {
            // set dimensions on the canvas
            canvas.setAttribute('width', window.innerWidth)
            canvas.setAttribute('height', window.innerHeight)
        }

        const setResizeFactors = () => {
            // set the x and y resizinf factor for cursor position
            dx = canvas.width / window.innerWidth
            dy = canvas.height / window.innerHeight
        }

        const handleResize = () => {
            setCanvasSize()
            setResizeFactors();
        }

        window.addEventListener("resize", handleResize)

        // Main function to render new DOM whenever activePalette changes
        const render = (palette) => {
            renderColorButtons(palette)
            setContextSettings(palette[0])
            setCanvasSize()
        }

        // User Input Event Handlers
        //----------------------------------------
        let firstX, firstY, secondX, secondY, paint

        function getCoordinates(event) {
            // check to see if mobile or desktop
            if (["mousedown", "mousemove"].includes(event.type)) {
                // click events
                return [event.pageX * dx, event.pageY * dy]
            } else {
                // touch coordinates
                return [event.touches[0].pageX * dx, event.touches[0].pageY * dy]
            }
        }

        function addClick(event, canvas) {
            let [x, y] = getCoordinates(event)

            secondX = firstX
            secondY = firstY
            firstX = x
            firstY = y
        }

        function draw() {
            context.beginPath()
            context.moveTo(secondX, secondY)
            context.lineTo(firstX, firstY)
            context.closePath()
            context.stroke()
        }

        function startPaint(event) {
            colorSelector.style.pointerEvents = 'none'
            paletteSelector.style.pointerEvents = 'none'

            addClick(event, this)
            paint = true
        }
        canvas.addEventListener('mousedown', startPaint)
        canvas.addEventListener('touchstart', startPaint)

        const exit = _ => {
            colorSelector.style.pointerEvents = 'all'
            paletteSelector.style.pointerEvents = 'all'

            paint = false
            firstX = null
            firstY = null
        }
        canvas.addEventListener('mouseup', exit)
        canvas.addEventListener('mouseleave', exit)
        canvas.addEventListener('touchend', exit)

        function endPaint(event) {
            if (paint) {
                addClick(event, this)
                draw()
            }
        }
        canvas.addEventListener('mousemove', endPaint)
        canvas.addEventListener('touchmove', endPaint)

        paletteSelector.onchange = (event) => {
            activePalette = event.target.value
            render(palettes[activePalette])
        }

        // Initialization when page is ready to load, runs once
        (function () {
            render(palettes[activePalette])
        })()

    </script>


</body>

</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值