| var canvas | |
| var context | |
| var getFromWeb = true | |
| var mouseDown = false | |
| var scale = .6 | |
| var outset = 15 | |
| var columnWidth = 256 | |
| var maxHeight = 256 | |
| var lastLink = null | |
| var lastLinkStr = null | |
| var labelback = {} | |
| var loadedImages = 0 | |
| var images = {} | |
| var imagesLength = 0; | |
| function recContains(rec, value) { | |
| if (!value.length) | |
| return 0 | |
| var lc = value.toLowerCase() | |
| if (rec.name.toLowerCase().indexOf(lc) >= 0) | |
| return 1 | |
| if (rec.code.toLowerCase().indexOf(lc) >= 0) | |
| return 2 | |
| return 3 | |
| } | |
| function setLink(recstr) { | |
| var under | |
| var link = recstr | |
| if (!link.startsWith("Sk")) { | |
| under = link.indexOf('_') | |
| link = link.substring(under + 1) | |
| } | |
| under = link.lastIndexOf('_') | |
| var len = link.length | |
| if (under == len - 2) { | |
| var letter = link[len - 1] | |
| if ('a' <= letter && letter <= 'z') { | |
| link = link.substr(0, len - 2) | |
| } else if ('0' <= letter && letter <= '9') { | |
| link = link.substr(0, len - 2) | |
| } | |
| } | |
| lastLinkStr = link | |
| } | |
| function showLink() { | |
| var link = lastLink.file + '#' + lastLinkStr | |
| context.save() | |
| context.font = "normal 16px Arial"; | |
| labelback.w = Math.max(labelback.w, context.measureText(link).width + 8) | |
| context.beginPath() | |
| context.rect(labelback.x, labelback.y, labelback.w, labelback.h) | |
| context.fillStyle = "rgba(232,180,220, 1)" | |
| context.fill() | |
| context.fillStyle = "rgba(64,32,48, 1)" | |
| context.fillText(link, labelback.x + 4, labelback.y + 16) | |
| context.restore() | |
| } | |
| function imageIterator(callout, state) { | |
| var row = outset + 30 | |
| var column = outset | |
| for (var recstr in pngs) { | |
| var rec = pngs[recstr] | |
| var contains = recContains(rec, input.value) | |
| if (3 == contains) | |
| continue; | |
| var height = rec.height < maxHeight ? rec.height : maxHeight | |
| if (callout(state, column, row, height, contains, recstr)) | |
| break; | |
| row += height + outset | |
| if (row >= canvas.height / scale) { | |
| row = 0 | |
| column += columnWidth + outset | |
| if (column >= canvas.width / scale) { | |
| break | |
| } | |
| } | |
| } | |
| } | |
| function handleMouseOver(event) { | |
| var callout = function(state, column, row, height, contains, recstr) { | |
| if (state.x >= column && state.x <= column + columnWidth && | |
| state.y >= row && state.y <= row + height) { | |
| document.body.style.cursor = "pointer" | |
| lastLink = pngs[recstr] | |
| setLink(recstr) | |
| showLink() | |
| return true | |
| } | |
| return false | |
| } | |
| var state = { | |
| x: (event.clientX - 5) / scale, | |
| y: (event.clientY - 7) / scale | |
| } | |
| document.body.style.cursor = "" | |
| lastLink = null | |
| imageIterator(callout, state) | |
| } | |
| function handleMouseClick() { | |
| if (null != lastLink) { | |
| var link = 'https://skia.org/user/api/' + lastLink.file + '#' + lastLinkStr | |
| window.location = link | |
| } | |
| } | |
| function doKeyPress(evt) { | |
| idiv.style.height = 20 | |
| input.focus() | |
| } | |
| function drawImage(hash, x, y, w, h, contains) { | |
| context.save() | |
| context.transform(scale, 0, 0, scale, 0, 0) | |
| context.save() | |
| context.beginPath() | |
| context.rect(x, y, w, h) | |
| context.clip() | |
| context.drawImage(images[hash], x, y) | |
| context.restore() | |
| context.beginPath() | |
| context.rect(x, y, w, h) | |
| context.strokeStyle = 1 == contains ? "red" : "black" | |
| context.stroke() | |
| context.restore() | |
| } | |
| function draw() { | |
| var callout = function(state, column, row, height, contains, recstr) { | |
| drawImage(pngs[recstr].hash, column, row, columnWidth, height, contains) | |
| return false | |
| } | |
| imageIterator(callout, null) | |
| } | |
| function sleep(ms) { | |
| return new Promise(resolve => setTimeout(resolve, ms)); | |
| } | |
| async function redraw() { | |
| context.strokeStyle = "white" | |
| context.beginPath() | |
| context.fillStyle = "white" | |
| context.rect(0, 30, canvas.width, canvas.height) | |
| context.fill() | |
| context.rect((256 + outset) * scale, 0, canvas.width, 30) | |
| context.fill() | |
| for (var image in images) { | |
| image.drawn = false | |
| } | |
| do { | |
| draw(); | |
| if (loadedImages >= imagesLength) | |
| break; | |
| console.debug(" loadedImages:" + loadedImages + " imagesLength:" + imagesLength) | |
| await sleep(1000); | |
| } while (true) | |
| } | |
| function resize() { | |
| setSize() | |
| redraw() | |
| } | |
| function setSize() { | |
| canvas.width = window.innerWidth - 20 | |
| canvas.height = window.innerHeight - 20 | |
| labelback.x = 0 | |
| labelback.y = canvas.height - 20 | |
| labelback.w = 0 | |
| labelback.h = 20 | |
| } | |
| function loadImages() { | |
| for (var recstr in pngs) { | |
| var rec = pngs[recstr] | |
| var image = new Image() | |
| images[rec.hash] = image | |
| if (getFromWeb) | |
| image.src = 'https://fiddle.skia.org/i/' | |
| image.src += rec.hash + '_raster.png' | |
| image.onload = function () { | |
| loadedImages += 1 | |
| } | |
| imagesLength += 1; | |
| } | |
| } | |
| function start() { | |
| loadImages() | |
| window.addEventListener('keypress', doKeyPress, true); | |
| window.addEventListener('keydown', doKeyPress, true); | |
| canvas = document.getElementById('canvas') | |
| context = canvas.getContext('2d') | |
| resize() | |
| } | |
| </script> | |
| </head> | |
| <body onLoad="start()" onresize="resize()"> | |
| <div style="height:0" id="idiv"> | |
| <input type="text" id="input" onkeypress="redraw()" onkeydown="redraw()"/> | |
| </div> | |
| <canvas id="canvas" width="750" height="500" | |
| onmousedown="mouseDown = true" | |
| onmouseup="mouseDown = false" | |
| onmousemove="handleMouseOver(event)" | |
| onclick="handleMouseClick()" | |
| ></canvas > | |
| </body> | |
| </html> |