Оптимизация javascript canvas

157
18 ноября 2018, 01:30

Вопрос возможно глупый, но анимация отображается как будто бы в замедленном времени. Я так понял надо оптимизировать код. Делал 2 канваса, не помогло так еще и код перестал работать. Делал код в одну строку помогло чуть-чуть.

		var canv = document.getElementById("canv"), 
		ctx = canv.getContext("2d"), 
		w = canv.width = window.innerWidth, 
		h = canv.height = window.innerHeight; 
		var log = val=>console.log(val) 
		var und; 
 
		var opts = { 
			colAmount: 10, 
			lettersInCol: 8, 
			spacing: 20, 
			letters: [0, 1], 
			bgc: 'rgba(17,16,17, 1)', 
			fc: 'rgba(220,219,221)', 
			timesAnim: 10, 
			rectsAm: 10, 
			rectsSpeed: .15 
		} 
		var colSize = (w - opts.spacing * opts.colAmount) / opts.colAmount; 
		var fSize = colSize / opts.lettersInCol / .98;  
		ctx.font = fSize + "px sans-serif"; 
 
		var coords = []; 
 
		var rects; 
		function makeRects(argument) { 
			rects = new Array(opts.rectsAm).fill().map(function() { 
				return { 
					col: 'rgba(17,16,17, alpha)', 
					sizeX: [colSize*2, w/100*75], 
					sizeY: [(h - opts.spacing * opts.colAmount) / opts.colAmount*2, h/100*75], 
					move: [Math.random() * opts.rectsSpeed * (Math.random()<0.5?1:-1), Math.random() * opts.rectsSpeed * (Math.random()<0.5?1:-1)], 
					pos: [Math.random()*w, Math.random()*h], 
					opac: 1, 
					maxSubOpac: .001 
				} 
			}) 
		} 
		makeRects() 
		for(let i = 0; i < opts.colAmount; i++) { 
			let target = (colSize + opts.spacing) * i + opts.spacing/2; 
			ctx.save() 
			ctx.fillStyle = 'rgba(0, 0, 0, 0.5)' 
			ctx.fillRect(target, 0, colSize, h) 
			ctx.restore() 
			for(let x = target; x < target+colSize; x += fSize) { 
				for(let y = fSize; y < h + fSize; y += fSize) { 
					coords.push({x:x,y:y, letter:opts.letters[Math.floor(Math.random() * opts.letters.length)]}) 
				} 
			} 
			function anim() { 
				ctx.clearRect(0,0,w,h); 
				ctx.fillStyle = opts.bgc 
				ctx.fillRect(0,0,w,h) 
				coords.map(function(cur) { 
					ctx.fillStyle = opts.fc 
					ctx.fillText(cur.letter, cur.x, cur.y) 
				}) 
 
				for(let a = 0; a < opts.timesAnim; a++) { 
					Math.random() < .25 ? (function() { 
						let i = Math.floor(Math.random() * coords.length); 
						switch(coords[i].letter) { 
							case opts.letters[0]: 
								coords[i].letter = opts.letters[1] 
							break; 
							case opts.letters[1]: 
								coords[i].letter = opts.letters[0] 
							break; 
						} 
					})() : und 
					setTimeout(function () { 
						let i = Math.floor(Math.random() * coords.length); 
						switch(coords[i].letter) { 
							case opts.letters[0]: 
								coords[i].letter = opts.letters[1] 
							break; 
							case opts.letters[1]: 
								coords[i].letter = opts.letters[0] 
							break; 
						} 
					}, Math.random()*2500) 
				} 
				rects.forEach(function(cur,i) { 
					cur.pos[0]+=cur.move[0]; 
					cur.pos[1]+=cur.move[1]; 
 
					cur.sizeX = Math.floor(cur.sizeX[0] + Math.random() * (cur.sizeX[1] + 1 - cur.sizeX[0])) ||cur.sizeX 
					cur.sizeY = Math.floor(cur.sizeY[0] + Math.random() * (cur.sizeY[1] + 1 - cur.sizeY[0])) ||cur.sizeY 
 
					cur.opac -= Math.random()*cur.maxSubOpac 
 
					ctx.fillStyle = cur.col.replace('alpha', cur.opac) 
					ctx.fillRect(cur.pos[0]-cur.sizeX/2, cur.pos[1]-cur.sizeY/2, cur.sizeX, cur.sizeY) 
 
					cur.opac <= 0?rects.splice(i, 1):und 
				}) 
				rects.length == 0?makeRects():und 
 
				window.requestAnimationFrame(anim) 
			} 
			anim() 
		}	 
    //однострочный код 
    //var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(b,d,a){b!=Array.prototype&&b!=Object.prototype&&(b[d]=a.value)};$jscomp.getGlobal=function(b){return"undefined"!=typeof window&&window===b?b:"undefined"!=typeof global&&null!=global?global:b};$jscomp.global=$jscomp.getGlobal(this);$jscomp.polyfill=function(b,d,a,c){if(d){a=$jscomp.global;b=b.split(".");for(c=0;c<b.length-1;c++){var e=b[c];e in a||(a[e]={});a=a[e]}b=b[b.length-1];c=a[b];d=d(c);d!=c&&null!=d&&$jscomp.defineProperty(a,b,{configurable:!0,writable:!0,value:d})}};$jscomp.polyfill("Array.prototype.fill",function(b){return b?b:function(b,a,c){var d=this.length||0;0>a&&(a=Math.max(0,d+a));if(null==c||c>d)c=d;c=Number(c);0>c&&(c=Math.max(0,d+c));for(a=Number(a||0);a<c;a++)this[a]=b;return this}},"es6","es3");var canv=document.getElementById("canv"),ctx=canv.getContext("2d"),w=canv.width=window.innerWidth,h=canv.height=window.innerHeight,log=function(b){return console.log(b)},und,opts={colAmount:10,lettersInCol:8,spacing:20,letters:[0,1],bgc:"rgba(17,16,17, 1)",fc:"rgba(220,219,221)",timesAnim:10,rectsAm:10,rectsSpeed:.15},colSize=(w-opts.spacing*opts.colAmount)/opts.colAmount,fSize=colSize/opts.lettersInCol/.98;ctx.font=fSize+"px sans-serif";var coords=[],rects;function makeRects(b){rects=Array(opts.rectsAm).fill().map(function(){return{col:"rgba(17,16,17, alpha)",sizeX:[2*colSize,w/100*75],sizeY:[(h-opts.spacing*opts.colAmount)/opts.colAmount*2,h/100*75],move:[Math.random()*opts.rectsSpeed*(.5>Math.random()?1:-1),Math.random()*opts.rectsSpeed*(.5>Math.random()?1:-1)],pos:[Math.random()*w,Math.random()*h],opac:1,maxSubOpac:.001}})}makeRects();for(var $jscomp$loop$0={},i=0;i<opts.colAmount;$jscomp$loop$0={anim:$jscomp$loop$0.anim},i++){$jscomp$loop$0.anim=function(b){return function(){ctx.clearRect(0,0,w,h);ctx.fillStyle=opts.bgc;ctx.fillRect(0,0,w,h);coords.map(function(a){ctx.fillStyle=opts.fc;ctx.fillText(a.letter,a.x,a.y)});for(var d=0;d<opts.timesAnim;d++).25>Math.random()?function(){var a=Math.floor(Math.random()*coords.length);switch(coords[a].letter){case opts.letters[0]:coords[a].letter=opts.letters[1];break;case opts.letters[1]:coords[a].letter=opts.letters[0]}}():und,setTimeout(function(){var a=Math.floor(Math.random()*coords.length);switch(coords[a].letter){case opts.letters[0]:coords[a].letter=opts.letters[1];break;case opts.letters[1]:coords[a].letter=opts.letters[0]}},2500*Math.random());rects.forEach(function(a,b){a.pos[0]+=a.move[0];a.pos[1]+=a.move[1];a.sizeX=Math.floor(a.sizeX[0]+Math.random()*(a.sizeX[1]+1-a.sizeX[0]))||a.sizeX;a.sizeY=Math.floor(a.sizeY[0]+Math.random()*(a.sizeY[1]+1-a.sizeY[0]))||a.sizeY;a.opac-=Math.random()*a.maxSubOpac;ctx.fillStyle=a.col.replace("alpha",a.opac);ctx.fillRect(a.pos[0]-a.sizeX/2,a.pos[1]-a.sizeY/2,a.sizeX,a.sizeY);0>=a.opac?rects.splice(b,1):und});0==rects.length?makeRects():und;window.requestAnimationFrame(b.anim)}}($jscomp$loop$0);for(var target=(colSize+opts.spacing)*i+opts.spacing/2,x=target;x<target+colSize;x+=fSize)for(var y=fSize;y<h+fSize;y+=fSize)coords.push({x:x,y:y,letter:opts.letters[Math.floor(Math.random()*opts.letters.length)]});$jscomp$loop$0.anim()};
<canvas id="canv" style="position: absolute;"></canvas>

Answer 1

TypeScript

онлайн конвертер https://www.typescriptlang.org/play/

namespace lib {
    let addTobody = el => { document.body.appendChild(el) }
    let callF = f => { f() }
    // --
    export let load_elStack = [] as HTMLElement[]
    export let load_fooStack = [] as Function[]
    // --
    window.addEventListener("load", () => {
        load_elStack.forEach(addTobody)
        load_fooStack.forEach(callF)
    })
}
namespace lib {
    const div: HTMLDivElement = document.createElement('div')
    lib.load_elStack.push(div)
    // window.addEventListener('load', () => { document.body.appendChild(div) })
    div.setAttribute('style', `
        position: fixed;
        background-color: grey;
        color: #7eee7e;
    `)
    let n = Date.now()
    let f = 0
    let q = n
    export function fps() {
        n = Date.now()
        f = 1 / ((n - q) / 1000)
        q = n
        div.innerHTML = 'fps: ' + (f | 0)
    }
}
// const canv: HTMLCanvasElement = document.getElementById("canv") as any // TODO:
const canv = document.createElement('canvas'); // TODO:
lib.load_elStack.push(canv)
// window.onload = () => {document.body.appendChild(canv)} // TODO:
const ctx = canv.getContext("2d")
lib.load_fooStack.push(() => {
    let w = canv.width = window.innerWidth
    let h = canv.height = window.innerHeight
    // var log = val => console.log(val)
    // let und = void 0; // TODO: удалить
    const opts = {
        colAmount: 10,
        lettersInCol: 8,
        spacing: 20,
        letters: [0, 1],
        bgc: 'rgba(17,16,17, 1)',
        fc: 'rgba(220,219,221)',
        timesAnim: 10,
        rectsAm: 10,
        rectsSpeed: .15
    }
    const colSize = (w - opts.spacing * opts.colAmount) / opts.colAmount;
    const fSize = colSize / opts.lettersInCol / .98;
    ctx.font = fSize + "px sans-serif";
    const coords = [];
    let rect = () => ({
        col: 'rgba(17,16,17, alpha)',
        sizeX: [
            colSize * 2,
            w / 100 * 75
        ],
        sizeY: [
            (h - opts.spacing * opts.colAmount) / opts.colAmount * 2,
            h / 100 * 75
        ],
        move: [
            Math.random() * opts.rectsSpeed * (Math.random() < 0.5 ? 1 : -1),
            Math.random() * opts.rectsSpeed * (Math.random() < 0.5 ? 1 : -1)
        ],
        pos: [
            Math.random() * w,
            Math.random() * h
        ],
        opac: 1,
        maxSubOpac: .001
    })
    let r = rect()       // TODO: для TS
    type rect = typeof r // TODO:
    let rects: rect[]
    function makeRects() {
        rects = Array.from({ length: opts.rectsAm }, rect)
    }
    makeRects()
    for (let i = 0; i < opts.colAmount; i++) {
        let target = (colSize + opts.spacing) * i + opts.spacing / 2;
        ctx.save()
        ctx.fillStyle = 'rgba(0, 0, 0, 0.5)'
        ctx.fillRect(target, 0, colSize, h)
        ctx.restore()
        for (var x = target; x < target + colSize; x += fSize) {
            for (var y = fSize; y < h + fSize; y += fSize) {
                coords.push({
                    x, y,
                    letter: opts.letters[Math.floor(Math.random() * opts.letters.length)] // TODO: проверить
                })
            }
        }
    }
    void function anim() {
        lib.fps()
        ctx.clearRect(0, 0, w, h);
        ctx.fillStyle = opts.bgc
        ctx.fillRect(0, 0, w, h)
        // coords.map(cur => { // TODO: map ???!
        coords.forEach(cur => {
            ctx.fillStyle = opts.fc
            ctx.fillText(cur.letter, cur.x, cur.y)
        })
        qq4()
        rects.forEach(qq3)
        rects.length == 0 && makeRects()
        window.requestAnimationFrame(anim)
    }()
    function qq4() {
        for (let a = 0; a < opts.timesAnim; a++) {
            // Math.random() < .25 && qq2() // TODO: сомневаюсь, что это нужно - удалить
            setTimeout(qq2, Math.random() * 2500)
        }
    }
    // ---------
    function qq2() {
        let i = Math.floor(Math.random() * coords.length);
        if (coords[i])
            switch (coords[i].letter) {
                case opts.letters[0]:
                    coords[i].letter = opts.letters[1]
                    break;
                case opts.letters[1]:
                    coords[i].letter = opts.letters[0]
                    break;
            }
    }
    function qq3(rect: rect, i) {
        let o = {
            r: Math.random()
            // get r() { return Math.random() } // TODO: или то или это
        }
        rect.pos[0] += rect.move[0];
        rect.pos[1] += rect.move[1];
        // cur.sizeX = Math.floor(cur.sizeX[0] + o.r * (cur.sizeX[1] + 1 - cur.sizeX[0])) || cur.sizeX // TODO: удалить
        // cur.sizeY = Math.floor(cur.sizeY[0] + o.r * (cur.sizeY[1] + 1 - cur.sizeY[0])) || cur.sizeY // TODO: удалить
        let x = Math.floor(rect.sizeX[0] + o.r * (rect.sizeX[1] + 1 - rect.sizeX[0])) //|| cur.sizeX // TODO: допилить или удалить cur.sizeX - массив
        let y = Math.floor(rect.sizeY[0] + o.r * (rect.sizeY[1] + 1 - rect.sizeY[0])) //|| cur.sizeY // TODO: допилить или удалить cur.sizeX - массив
        rect.opac -= o.r * rect.maxSubOpac
        ctx.fillStyle = rect.col.replace('alpha', '' + rect.opac)
        // ctx.fillRect(cur.pos[0] - cur.sizeX / 2, cur.pos[1] - cur.sizeY / 2, cur.sizeX, cur.sizeY) // TODO: удалить
        ctx.fillRect(rect.pos[0] - x / 2, rect.pos[1] - y / 2, x, y)
        rect.opac <= 0 && rects.splice(i, 1)
    }
})
READ ALSO
Как вставить карту с геокодированием?

Как вставить карту с геокодированием?

Как вставить карту как на странице в Яндексе https://techyandex

143
sapui5 smartfilterbar filter positioning

sapui5 smartfilterbar filter positioning

In my app i have smart filter bar with smart filtersI'm using annotations on front end (no possibility to generate it from back-end, unfortunately)

128
Изменение рендера объекта vue.js

Изменение рендера объекта vue.js

Пример: есть объект который приходит с сервера со значениями

126