1window.addEventListener('load', () => { 2 function preloadImages() { 3 const flows_imageSrc = (i) => `static/demo/flows/${String(i).padStart(5, '0')}.png`; 4 const flows_maskSrc = (i) => `static/demo/flows/${String(i).padStart(5, '0')}_occ.png` 5 const swing_imageSrc = (i) => `static/demo/swing/${String(i).padStart(5, '0')}.jpg` 6 7 function preload(srcGetter) { 8 result = []; 9 for (var i = 0; i < 60; i++) { 10 const img = new Image(); 11 img.src = srcGetter(i); 12 result.push(img); 13 } 14 return result; 15 } 16 17 return { 18 flow: preload(flows_imageSrc), 19 mask: preload(flows_maskSrc), 20 swing: preload(swing_imageSrc) 21 } 22 } 23 images = preloadImages(); 24 25 // slide follow animation 26 function displayFramesWithSlider(framePathPrefix, totalFrames) { 27 const frame = document.getElementById("frame"); 28 const slider = document.getElementById("slider"); 29 const sliderLabel = document.getElementById("slider-label"); 30 31 // init slider 32 slider.setAttribute("max", totalFrames); 33 slider.setAttribute("min", 1); 34 35 slider.addEventListener("input", function () { 36 const frameIndex = slider.value; 37 const framePath = framePathPrefix + String(frameIndex).padStart(5, '0') + ".jpg"; 38 frame.src = framePath; 39 // sliderLabel.textContent = "Slider: " + frameIndex; 40 }); 41 } 42 43 // Usage 44 displayFramesWithSlider("static/demo/swing/", 59); // Example with 100 frames 45 46 const imageBoard1 = document.querySelectorAll('.image-board')[0]; 47 const clickableImage1 = imageBoard1.querySelector('.clickable-image'); 48 const imageBoard2 = document.querySelectorAll('.image-board')[1]; 49 const clickableImage2 = imageBoard2.querySelector('.clickable-image'); 50 const initialDot = document.getElementById('initial-dot'); 51 const slider = document.getElementById('slider'); 52 const clearBtn = document.getElementById('clear-btn'); 53 clearBtn.addEventListener('click', function () { 54 // remove original dot & add a fixed dot 55 const existingDots1 = imageBoard1.querySelectorAll('.dot'); 56 existingDots1.forEach(dot => imageBoard1.removeChild(dot)); 57 const existingDots2 = imageBoard2.querySelectorAll('.dot'); 58 existingDots2.forEach(dot => imageBoard2.removeChild(dot)); 59 const existingCross2 = imageBoard2.querySelectorAll('.cross'); 60 existingCross2.forEach(cross => imageBoard2.removeChild(cross)); 61 }) 62 63 // var currentValue = slider.value; 64 // console.log('@@board-left', clickableImage1.offsetLeft); 65 const padX = clickableImage1.offsetLeft; 66 const padY = clickableImage1.offsetLeft; 67 const dotRadius = 6; 68 const crossRadius = 6; 69 // console.log('@@padX', padX); 70 // console.log('@@padY', padY); 71 let RandColor = getRandomColor(); 72 initialDot.style.backgroundColor = RandColor; 73 clickableImage1.addEventListener('mousemove', function (event) { 74 initialDot.style.left = `${event.offsetX + padX - dotRadius}px`; 75 initialDot.style.top = `${event.offsetY + padY - dotRadius}px`; 76 }) 77 78 function getRandomColor() { 79 const letters = '0123456789ABCDEF';
80 let color = '#'; 81 for (let i = 0; i < 6; i++) { 82 color += letters[Math.floor(Math.random() * 16)]; 83 } 84 // exclude #000 85 if (color === '#000000') { 86 return getRandomColor(); 87 } 88 return color; 89 } 90 91 function calculateNaturalLocation(x, y) { 92 const scaleX = clickableImage1.naturalWidth / clickableImage1.width; 93 const scaleY = clickableImage1.naturalHeight / clickableImage1.height; 94 const naturalX = Math.round(x * scaleX); 95 const naturalY = Math.round(y * scaleY); 96 return { x: naturalX, y: naturalY }; 97 } 98 99 function calculateViewLocation(x, y) { 100 const scaleX = clickableImage2.width / clickableImage2.naturalWidth; 101 const scaleY = clickableImage2.height / clickableImage2.naturalHeight; 102 const viewX = Math.round(x * scaleX); 103 const viewY = Math.round(y * scaleY); 104 return { x: viewX, y: viewY }; 105 } 106 107 108 function transferDots() { 109 var imageSrc = "static/demo/flows/" + String(slider.value).padStart(5, '0') + ".png"; 110 var maskSrc = "static/demo/flows/" + String(slider.value).padStart(5, '0') + "_occ.png"; 111 112 var image = images.flow[slider.value]; 113 var mask = images.mask[slider.value]; 114 115 var image_canvas = document.createElement('canvas'); 116 image_canvas.width = image.width; 117 image_canvas.height = image.height; 118 var image_ctx = image_canvas.getContext('2d', { willReadFrequently: true }); 119 image_ctx.drawImage(image, 0, 0); 120 121 var mask_canvas = document.createElement('canvas'); 122 mask_canvas.width = mask.width; 123 mask_canvas.height = mask.height; 124 var mask_ctx = mask_canvas.getContext('2d', { willReadFrequently: true }); 125 mask_ctx.drawImage(mask, 0, 0); 126 127 function read_pixel(ctx, x, y) { 128 var pixelData = ctx.getImageData(x, y, 1, 1).data; 129 var red = new Int32Array([pixelData[0]])[0]; 130 var green = new Int32Array([pixelData[1]])[0]; 131 var blue = new Int32Array([pixelData[2]])[0]; 132 var alpha = new Int32Array([pixelData[3]])[0]; 133 return { 134 red: red, 135 green: green, 136 blue: blue, 137 alpha: alpha 138 }; 139 } 140 // Remove old dots. 141 for (olddot of imageBoard2.querySelectorAll('div')) { 142 olddot.remove(); 143 } 144 // Add new ones. 145 imageBoard1.querySelectorAll('.dot').forEach(dot => { 146 const x = dot.natural.x; 147 const y = dot.natural.y; 148 const color = dot.style.backgroundColor; 149 150 var { red, green, blue, alpha } = read_pixel(image_ctx, x, y); 151 flow_x = ((red << 4) | (green >> 4)) - 2048; 152 flow_y = ((blue << 4) | (green & 0b1111)) - 2048; 153 154 const loc2 = calculateViewLocation(x + flow_x, y + flow_y); 155 if (loc2.x > clickableImage2.width || loc2.y > clickableImage2.height 156 || loc2.x < 0 || loc2.y < 0 157 ) { 158 // Out of bounds, don't show this dot. 159 return; 160 } 161 var { red, green, blue, alpha } = read_pixel(mask_ctx, x, y); 162 const visible = (red == 0); 163 const dot2 = document.createElement('div'); 164 dot2.style.backgroundColor = color; 165 if (visible) { 166 dot2.classList.add('dot'); 167 dot2.style.left = `${loc2.x + padX - dotRadius}px`; 168 dot2.style.top = `${loc2.y + padY - dotRadius}px`; 169 } else { 170 dot2.classList.add('cross'); 171 dot2.style.left = `${loc2.x + padX - crossRadius}px`; 172 dot2.style.top = `${loc2.y + padY - crossRadius}px`; 173 } 174 imageBoard2.appendChild(dot2); 175 }); 176 } 177 178 clickableImage1.addEventListener('click', function (event) { 179 // console.log("@before input: original dot location", event.offsetX, event.offsetY); 180 // dot coordinate 181 const offsetX = event.offsetX + padX - dotRadius; 182 const offsetY = event.offsetY + padY - dotRadius; 183 // randColor = getRandomColor(); 184 const dot1 = document.createElement('div'); 185 dot1.classList.add('dot'); 186 dot1.style.backgroundColor = RandColor; 187 // dot1.color = RandColor; 188 dot1.style.left = `${offsetX}px`; 189 dot1.style.top = `${offsetY}px`; 190 dot1.natural = calculateNaturalLocation(event.offsetX, event.offsetY); 191 imageBoard1.appendChild(dot1); 192 // update color 193 RandColor = getRandomColor(); 194 initialDot.style.backgroundColor = RandColor; 195 // console.log('Dot Location:', { offsetX, offsetY }); 196 197 // the coordinate of pointer in img 198 const p_x = event.offsetX; 199 const p_y = event.offsetY; 200 201 // console.log('@@Visual Img Point Location:', { p_x, p_y }); 202 console.log('@@color', RandColor); 203 transferDots(); 204 205 function getCurrentSliderValue(sliderId) { 206 const slider = document.getElementById(sliderId); 207 const sliderValue = slider.value; 208 return sliderValue; 209 } 210 const sliderValue = getCurrentSliderValue('slider'); 211 console.log('Slider value:', sliderValue); 212 }); 213 214 slider.addEventListener('input', transferDots); 215});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.