Canvas 右侧导航面板预览插件

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Canvas 右侧导航面板预览插件</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            font-family: Arial, sans-serif;
            overflow: hidden;
        }
        
        #main-container {
            display: flex;
            height: 100vh;
        }
        
        #canvas-container {
            flex: 1;
            position: relative;
            overflow: hidden;
        }
        
        canvas {
            display: block;
            background-color: #f0f0f0;
        }
        
        #nav-panel {
            width: 300px;
            background-color: #2c3e50;
            color: white;
            padding: 15px;
            box-sizing: border-box;
            overflow-y: auto;
            position: relative;
            transition: transform 0.3s ease;
            box-shadow: -2px 0 5px rgba(0, 0, 0, 0.2);
        }
        
        #drag-handle {
            width: 10px;
            height: 100%;
            background-color: #34495e;
            position: absolute;
            left: 0;
            top: 0;
            cursor: col-resize;
        }
        
        .panel-section {
            margin-bottom: 20px;
            border-bottom: 1px solid #34495e;
            padding-bottom: 15px;
        }
        
        .panel-section h3 {
            margin-top: 0;
            color: #ecf0f1;
        }
        
        .thumbnail {
            width: 100%;
            height: 120px;
            background-color: #34495e;
            margin-bottom: 10px;
            cursor: pointer;
            transition: all 0.2s;
            overflow: hidden;
        }
        
        .thumbnail:hover {
            transform: scale(1.02);
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
        }
        
        .thumbnail.active {
            border: 2px solid #3498db;
        }
        
        button {
            background-color: #3498db;
            color: white;
            border: none;
            padding: 8px 15px;
            border-radius: 4px;
            cursor: pointer;
            margin-right: 10px;
            margin-bottom: 10px;
        }
        
        button:hover {
            background-color: #2980b9;
        }
        
        .color-picker {
            display: flex;
            flex-wrap: wrap;
            margin-bottom: 15px;
        }
        
        .color-option {
            width: 30px;
            height: 30px;
            margin: 5px;
            cursor: pointer;
            border: 2px solid transparent;
        }
        
        .color-option:hover, .color-option.selected {
            border-color: white;
        }
        
        #toggle-panel {
            position: absolute;
            top: 10px;
            right: 10px;
            background-color: #2c3e50;
            color: white;
            border: none;
            width: 30px;
            height: 30px;
            border-radius: 50%;
            cursor: pointer;
            z-index: 100;
            display: none;
        }
        
        @media (max-width: 768px) {
            #nav-panel {
                position: absolute;
                right: 0;
                top: 0;
                height: 100%;
                transform: translateX(100%);
                z-index: 99;
            }
            
            #nav-panel.open {
                transform: translateX(0);
            }
            
            #toggle-panel {
                display: block;
            }
        }
    </style>
</head>
<body>
    <div id="main-container">
        <div id="canvas-container">
            <canvas id="main-canvas"></canvas>
            <button id="toggle-panel">≡</button>
        </div>
        <div id="nav-panel">
            <div id="drag-handle"></div>
            <div class="panel-section">
                <h3>预览导航</h3>
                <div id="thumbnails-container">
                </div>
            </div>
            
            <div class="panel-section">
                <h3>工具</h3>
                <button id="clear-btn">清空画布</button>
                <button id="save-btn">保存图像</button>
            </div>
            
            <div class="panel-section">
                <h3>画笔设置</h3>
                <label for="brush-size">画笔大小:</label>
                <input type="range" id="brush-size" min="1" max="50" value="5">
                <span id="brush-size-value">5</span>
                
                <h4>颜色选择:</h4>
                <div class="color-picker">
                    <div class="color-option selected" style="background-color: #000000;" data-color="#000000"></div>
                    <div class="color-option" style="background-color: #ff0000;" data-color="#ff0000"></div>
                    <div class="color-option" style="background-color: #00ff00;" data-color="#00ff00"></div>
                    <div class="color-option" style="background-color: #0000ff;" data-color="#0000ff"></div>
                    <div class="color-option" style="background-color: #ffff00;" data-color="#ffff00"></div>
                    <div class="color-option" style="background-color: #ff00ff;" data-color="#ff00ff"></div>
                    <div class="color-option" style="background-color: #00ffff;" data-color="#00ffff"></div>
                    <div class="color-option" style="background-color: #ffffff;" data-color="#ffffff"></div>
                </div>
            </div>
            
            <div class="panel-section">
                <h3>关于</h3>
                <p>这是一个Canvas绘图工具,带有右侧导航面板预览功能。</p>

            </div>
        </div>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            // 获取DOM元素
            const canvas = document.getElementById('main-canvas');
            const ctx = canvas.getContext('2d');
            const navPanel = document.getElementById('nav-panel');
            const dragHandle = document.getElementById('drag-handle');
            const togglePanelBtn = document.getElementById('toggle-panel');
            const clearBtn = document.getElementById('clear-btn');
            const saveBtn = document.getElementById('save-btn');
            const brushSizeInput = document.getElementById('brush-size');
            const brushSizeValue = document.getElementById('brush-size-value');
            const colorOptions = document.querySelectorAll('.color-option');
            const thumbnailsContainer = document.getElementById('thumbnails-container');
            
            // 设置Canvas大小
            function resizeCanvas() {
                const container = document.getElementById('canvas-container');
                canvas.width = container.clientWidth;
                canvas.height = container.clientHeight;
                
                // 重绘内容
                if (localStorage.getItem('canvasData')) {
                    restoreCanvas();
                }
                
                // 更新缩略图
                updateThumbnails();
            }
            
            // 初始化Canvas
            resizeCanvas();
            window.addEventListener('resize', resizeCanvas);
            
            // 绘图状态
            let isDrawing = false;
            let lastX = 0;
            let lastY = 0;
            let currentColor = '#000000';
            let currentBrushSize = 5;
            
            // 设置画笔颜色
            colorOptions.forEach(option => {
                option.addEventListener('click', function() {
                    colorOptions.forEach(opt => opt.classList.remove('selected'));
                    this.classList.add('selected');
                    currentColor = this.dataset.color;
                });
            });
            
            // 设置画笔大小
            brushSizeInput.addEventListener('input', function() {
                currentBrushSize = this.value;
                brushSizeValue.textContent = this.value;
            });
            
            // 绘图函数
            function draw(e) {
                if (!isDrawing) return;
                
                ctx.beginPath();
                ctx.moveTo(lastX, lastY);
                ctx.lineTo(e.offsetX, e.offsetY);
                ctx.strokeStyle = currentColor;
                ctx.lineWidth = currentBrushSize;
                ctx.lineCap = 'round';
                ctx.lineJoin = 'round';
                ctx.stroke();
                
                [lastX, lastY] = [e.offsetX, e.offsetY];
                
                // 保存Canvas状态
                saveCanvasState();
                
                // 更新缩略图
                updateThumbnails();
            }
            
            // 鼠标事件监听
            canvas.addEventListener('mousedown', (e) => {
                isDrawing = true;
                [lastX, lastY] = [e.offsetX, e.offsetY];
            });
            
            canvas.addEventListener('mousemove', draw);
            canvas.addEventListener('mouseup', () => isDrawing = false);
            canvas.addEventListener('mouseout', () => isDrawing = false);
            
            // 触摸事件支持
            canvas.addEventListener('touchstart', (e) => {
                e.preventDefault();
                const touch = e.touches[0];
                const mouseEvent = new MouseEvent('mousedown', {
                    clientX: touch.clientX,
                    clientY: touch.clientY
                });
                canvas.dispatchEvent(mouseEvent);
            });
            
            canvas.addEventListener('touchmove', (e) => {
                e.preventDefault();
                const touch = e.touches[0];
                const mouseEvent = new MouseEvent('mousemove', {
                    clientX: touch.clientX,
                    clientY: touch.clientY
                });
                canvas.dispatchEvent(mouseEvent);
            });
            
            canvas.addEventListener('touchend', (e) => {
                e.preventDefault();
                const mouseEvent = new MouseEvent('mouseup', {});
                canvas.dispatchEvent(mouseEvent);
            });
            
            // 清空画布
            clearBtn.addEventListener('click', function() {
                if (confirm('确定要清空画布吗?')) {
                    ctx.clearRect(0, 0, canvas.width, canvas.height);
                    localStorage.removeItem('canvasData');
                    updateThumbnails();
                }
            });
            
            // 保存图像
            saveBtn.addEventListener('click', function() {
                const link = document.createElement('a');
                link.download = 'canvas-drawing.png';
                link.href = canvas.toDataURL('image/png');
                link.click();
            });
            
            // 保存Canvas状态
            function saveCanvasState() {
                localStorage.setItem('canvasData', canvas.toDataURL());
            }
            
            // 恢复Canvas状态
            function restoreCanvas() {
                const img = new Image();
                img.onload = function() {
                    ctx.drawImage(img, 0, 0);
                };
                img.src = localStorage.getItem('canvasData');
            }
            
            // 创建缩略图
            function createThumbnail(index) {
                const thumbnail = document.createElement('div');
                thumbnail.className = 'thumbnail';
                thumbnail.dataset.index = index;
                
                const canvas = document.createElement('canvas');
                canvas.width = 280;
                canvas.height = 120;
                thumbnail.appendChild(canvas);
                
                // 从本地存储加载图像
                const img = new Image();
                img.onload = function() {
                    const ctx = canvas.getContext('2d');
                    ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
                };
                
                const savedData = localStorage.getItem(`canvasSnapshot_${index}`);
                if (savedData) {
                    img.src = savedData;
                }
                
                thumbnail.addEventListener('click', function() {
                    // 恢复这个版本的画布
                    if (savedData) {
                        const restoreImg = new Image();
                        restoreImg.onload = function() {
                            ctx.clearRect(0, 0, canvas.width, canvas.height);
                            ctx.drawImage(restoreImg, 0, 0);
                            saveCanvasState();
                        };
                        restoreImg.src = savedData;
                    }
                });
                
                return thumbnail;
            }
            
            // 更新缩略图
            function updateThumbnails() {
                // 保存当前状态为快照
                const timestamp = new Date().getTime();
                localStorage.setItem(`canvasSnapshot_${timestamp}`, canvas.toDataURL());
                
                // 保留最新的5个缩略图
                const keys = Object.keys(localStorage)
                    .filter(key => key.startsWith('canvasSnapshot_'))
                    .sort()
                    .reverse()
                    .slice(0, 5);
                
                thumbnailsContainer.innerHTML = '';
                keys.forEach((key, index) => {
                    const thumbnail = createThumbnail(key.split('_')[1]);
                    thumbnailsContainer.appendChild(thumbnail);
                });
            }
            
            // 面板拖动功能
            let isDragging = false;
            let startX, startWidth;
            
            dragHandle.addEventListener('mousedown', function(e) {
                isDragging = true;
                startX = e.clientX;
                startWidth = navPanel.offsetWidth;
                document.body.style.cursor = 'col-resize';
                e.preventDefault();
            });
            
            document.addEventListener('mousemove', function(e) {
                if (!isDragging) return;
                
                const newWidth = startWidth + (startX - e.clientX);
                if (newWidth > 200 && newWidth < 500) {
                    navPanel.style.width = `${newWidth}px`;
                }
            });
            
            document.addEventListener('mouseup', function() {
                isDragging = false;
                document.body.style.cursor = '';
            });
            
            // 切换面板显示/隐藏
            togglePanelBtn.addEventListener('click', function() {
                navPanel.classList.toggle('open');
            });
            
            // 初始化缩略图
            updateThumbnails();
        });
    </script>
</body>
</html>

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值