fix(i18n): add 'home' body class to English homepage so section__title margin applies
This commit is contained in:
1 parent
9d78567386
commit
939ce8fcc9
88 files changed
+1830
-2
No files matched your search
BIN
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
+18
@@ -0,0 +1,18 @@
|
||||
import puppeteer from "puppeteer";
|
||||
const b = await puppeteer.launch({ args: ["--no-sandbox","--disable-dev-shm-usage"] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({ width: 768, height: 900, deviceScaleFactor: 1 });
|
||||
await p.goto("http://localhost:4175/", { waitUntil: "networkidle0" });
|
||||
await p.evaluate(() => window.scrollTo(0, 400));
|
||||
await new Promise(r=>setTimeout(r,400));
|
||||
await p.evaluate(() => document.querySelector("[data-nav-more-btn]")?.click());
|
||||
await new Promise(r=>setTimeout(r,300));
|
||||
const m = await p.evaluate(() => {
|
||||
const menu = document.querySelector("#nav-more-menu-floating");
|
||||
if (!menu || menu.hidden) return { hidden: true };
|
||||
const mr = menu.getBoundingClientRect();
|
||||
const vw = document.documentElement.clientWidth;
|
||||
return { rightFromEdge: Math.round(vw - mr.right), edgePad: getComputedStyle(document.documentElement).getPropertyValue("--edge-pad").trim() };
|
||||
});
|
||||
console.log("MENU@768:", JSON.stringify(m));
|
||||
await b.close();
|
||||
@@ -0,0 +1,23 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
const errs=[]; p.on('pageerror',e=>errs.push(e.message)); p.on('console',m=>{if(m.type()==='error')errs.push(m.text());});
|
||||
await p.setViewport({width:1100,height:1500});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1500));
|
||||
await p.evaluate(()=>document.querySelector('#sec-all-shaders')?.scrollIntoView());
|
||||
await new Promise(r=>setTimeout(r,1500));
|
||||
const r = await p.evaluate(()=>{
|
||||
const cells=[...document.querySelectorAll('[data-shader-cell]')];
|
||||
const cellInfo=cells.map(c=>{const m=c.querySelector('.card-shader')?.paperShaderMount; return {key:c.dataset.shaderCell, mounted:!!m, speed:m?.currentSpeed, frame:m?Math.round(m.getCurrentFrame()):null};});
|
||||
const demo=document.querySelector('[data-shader-demo]');
|
||||
const demoMounted=!!demo.querySelector('.card-shader')?.paperShaderMount;
|
||||
// переключим на spiral и проверим label
|
||||
const btn=document.querySelector('[data-shader-switch="spiral"]');
|
||||
let labelAfter=null;
|
||||
if(btn){ btn.click(); labelAfter=document.querySelector('[data-shader-label]')?.textContent; }
|
||||
return { cellCount: cells.length, cellInfo, demoMounted, labelAfter };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
console.log('ERRS', errs.slice(0,8));
|
||||
await b.close();
|
||||
@@ -0,0 +1,20 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
await p.evaluate(()=>document.querySelector('[data-shader-demo]').scrollIntoView({block:'center'}));
|
||||
await new Promise(r=>setTimeout(r,600));
|
||||
const snap = ()=>p.evaluate(()=>{
|
||||
const cv=document.querySelector('[data-shader-demo] canvas');
|
||||
const gl=cv.getContext('webgl2',{preserveDrawingBuffer:true})||cv.getContext('webgl',{preserveDrawingBuffer:true});
|
||||
const a=new Uint8Array(4*9); let k=0;
|
||||
for(const [x,y] of [[20,20],[100,80],[200,150],[50,180],[300,40]]){ gl.readPixels(x,y,1,1,gl.RGBA,gl.UNSIGNED_BYTE,a.subarray(k,k+4)); k+=4; }
|
||||
return Array.from(a).join(',');
|
||||
});
|
||||
const s1=await snap(); await new Promise(r=>setTimeout(r,700)); const s2=await snap();
|
||||
console.log('frame1:', s1);
|
||||
console.log('frame2:', s2);
|
||||
console.log('MOVING:', s1!==s2);
|
||||
await b.close();
|
||||
@@ -0,0 +1,18 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
import sharp from 'sharp';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
await p.evaluate(()=>document.querySelector('[data-shader-demo]').scrollIntoView({block:'center'}));
|
||||
await new Promise(r=>setTimeout(r,600));
|
||||
async function shot(){ const el=await p.$('[data-shader-demo]'); await el.screenshot({path:'/tmp/a.png'});
|
||||
const {data,info}=await sharp('/tmp/a.png').raw().toBuffer({resolveWithObject:true});
|
||||
return {w:info.width,h:info.height,data}; }
|
||||
const s1=await shot(); await new Promise(r=>setTimeout(r,800)); const s2=await shot();
|
||||
// сравним центральные пиксели
|
||||
function center(d,info){ const i=((info.height>>1)*info.width+(info.width>>1))*3; return [d[i],d[i+1],d[i+2]]; }
|
||||
const c1=center(s1.data,s1), c2=center(s2.data,s2);
|
||||
console.log('center px t1:', c1, ' t2:', c2, ' MOVED:', JSON.stringify(c1)!==JSON.stringify(c2));
|
||||
await b.close();
|
||||
@@ -0,0 +1,22 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
import sharp from 'sharp';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const top = await p.evaluate(()=>{ const r=document.querySelector('[data-shader-demo]').getBoundingClientRect(); return r.top+window.scrollY; });
|
||||
await p.evaluate((t)=>window.scrollTo(0, t-150), top);
|
||||
await new Promise(r=>setTimeout(r,700));
|
||||
async function region(){ await p.screenshot({path:'/tmp/r.png'});
|
||||
const rect = await p.evaluate(()=>{ const r=document.querySelector('[data-shader-demo]').getBoundingClientRect(); return {x:r.x,y:r.y,w:r.width,h:r.height}; });
|
||||
const {data,info}=await sharp('/tmp/r.png').raw().toBuffer({resolveWithObject:true});
|
||||
// хеш центральной полосы
|
||||
const samples=[]; const y=Math.floor(rect.y+rect.h*0.4);
|
||||
for(let x=Math.floor(rect.x+20); x<rect.x+rect.w-20; x+=15){ const i=(Math.floor(y)*info.width+Math.floor(x))*3; samples.push(data[i]+','+data[i+1]+','+data[i+2]); }
|
||||
return samples.join('|');
|
||||
}
|
||||
const a=await region(); await new Promise(r=>setTimeout(r,800)); const c=await region();
|
||||
console.log('moved:', a!==c);
|
||||
console.log('t1 head:', a.slice(0,60)); console.log('t2 head:', c.slice(0,60));
|
||||
await b.close();
|
||||
@@ -0,0 +1,22 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
import sharp from 'sharp';
|
||||
import crypto from 'crypto';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const top = await p.evaluate(()=>{ const r=document.querySelector('[data-shader-demo]').getBoundingClientRect(); return r.top+window.scrollY; });
|
||||
await p.evaluate((t)=>window.scrollTo(0, t-150), top);
|
||||
await new Promise(r=>setTimeout(r,700));
|
||||
async function hash(){ await p.screenshot({path:'/tmp/rl.png'});
|
||||
const rect = await p.evaluate(()=>{ const r=document.querySelector('[data-shader-demo]').getBoundingClientRect(); return {x:r.x,y:r.y,w:r.width,h:r.height}; });
|
||||
const {data,info}=await sharp('/tmp/rl.png').raw().toBuffer({resolveWithObject:true});
|
||||
const x0=Math.floor(rect.x),y0=Math.floor(rect.y),x1=Math.floor(rect.x+rect.w),y1=Math.floor(rect.y+rect.h);
|
||||
const buf=Buffer.alloc((x1-x0)*(y1-y0)*3);
|
||||
let k=0; for(let y=y0;y<y1;y++) for(let x=x0;x<x1;x++){ const i=(y*info.width+x)*3; buf[k++]=data[i];buf[k++]=data[i+1];buf[k++]=data[i+2]; }
|
||||
return crypto.createHash('md5').update(buf).digest('hex');
|
||||
}
|
||||
const a=await hash(); await new Promise(r=>setTimeout(r,3000)); const c=await hash();
|
||||
console.log('hash1', a); console.log('hash2', c); console.log('ANIMATED:', a!==c);
|
||||
await b.close();
|
||||
@@ -0,0 +1,26 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:800,height:600});
|
||||
await p.goto('about:blank',{waitUntil:'load'});
|
||||
await new Promise(r=>setTimeout(r,300));
|
||||
const r = await p.evaluate(()=>{
|
||||
const cv=document.createElement('canvas'); cv.width=64; cv.height=64; document.body.appendChild(cv);
|
||||
const gl=cv.getContext('webgl2');
|
||||
if(!gl) return {webgl2:false};
|
||||
const vs=`#version 300 es\nin vec4 a_position; void main(){ gl_Position=a_position; }`;
|
||||
const fs=`#version 300 es\nprecision mediump float; out vec4 o; void main(){ o=vec4(1.0,0.3,0.0,1.0); }`;
|
||||
const mk=(s)=>{const sh=gl.createShader(s.includes('main(){ gl_Position')?gl.VERTEX_SHADER:gl.FRAGMENT_SHADER);gl.shaderSource(sh,s);gl.compileShader(sh);return {sh,ok:gl.getShaderParameter(sh,gl.COMPILE_STATUS),log:gl.getShaderInfoLog(sh)};};
|
||||
const v=mk(vs), f=mk(fs);
|
||||
const prog=gl.createProgram(); gl.attachShader(prog,v.sh); gl.attachShader(prog,f.sh); gl.linkProgram(prog);
|
||||
const linked=gl.getProgramParameter(prog,gl.LINK_STATUS);
|
||||
gl.useProgram(prog);
|
||||
const buf=gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER,buf); gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]),gl.STATIC_DRAW);
|
||||
const loc=gl.getAttribLocation(prog,'a_position'); gl.enableVertexAttribArray(loc); gl.vertexAttribPointer(loc,2,gl.FLOAT,false,0,0);
|
||||
gl.clearColor(0,0,0,1); gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
gl.drawArrays(gl.TRIANGLES,0,6);
|
||||
const px=new Uint8Array(4); gl.readPixels(32,32,1,1,gl.RGBA,gl.UNSIGNED_BYTE,px);
|
||||
return { webgl2:true, vsOk:v.ok, fsOk:f.ok, fsLog:f.log, linked, center:Array.from(px) };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
import sharp from 'sharp';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const top = await p.evaluate(()=>{ const r=document.querySelector('[data-shader-demo]').getBoundingClientRect(); return r.top+window.scrollY; });
|
||||
await p.evaluate((t)=>window.scrollTo(0, t-150), top);
|
||||
await new Promise(r=>setTimeout(r,800));
|
||||
await p.screenshot({path:'/tmp/sec.png'});
|
||||
const rect = await p.evaluate(()=>{ const r=document.querySelector('[data-shader-demo]').getBoundingClientRect(); return {x:r.x,y:r.y,w:r.width,h:r.height}; });
|
||||
const {data,info}=await sharp('/tmp/sec.png').raw().toBuffer({resolveWithObject:true});
|
||||
const x0=Math.floor(rect.x), y0=Math.floor(rect.y), x1=Math.floor(rect.x+rect.w), y1=Math.floor(rect.y+rect.h);
|
||||
let maxR=0,maxG=0,maxB=0, brightPx=0, n=0;
|
||||
for(let y=Math.max(0,y0);y<Math.min(info.height,y1);y++) for(let x=Math.max(0,x0);x<Math.min(info.width,x1);x++){ const i=(y*info.width+x)*3; maxR=Math.max(maxR,data[i]);maxG=Math.max(maxG,data[i+1]);maxB=Math.max(maxB,data[i+2]); if(data[i]+data[i+1]+data[i+2]>250) brightPx++; n++; }
|
||||
console.log('max channel values in demo card:', maxR, maxG, maxB, 'bright pixels:', brightPx, '/', n);
|
||||
await b.close();
|
||||
@@ -0,0 +1,21 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
const errs=[]; p.on('pageerror',e=>errs.push(e.message)); p.on('console',m=>{if(m.type()==='error')errs.push(m.text());});
|
||||
await p.setViewport({width:1100,height:1500});
|
||||
await p.goto('http://10.200.201.3:4175/',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,800));
|
||||
const r = await p.evaluate(()=>{
|
||||
const pick = (sel)=>{ const el=document.querySelector(sel); if(!el) return null;
|
||||
const cs=getComputedStyle(el);
|
||||
return { boxShadow: cs.boxShadow.slice(0,60), shadowLen: cs.boxShadow.length, transform: cs.transform, bg: cs.backgroundImage.slice(0,40) }; };
|
||||
return {
|
||||
mp: pick('.mp-card'),
|
||||
portfolio: pick('.portfolio-card'),
|
||||
skill: pick('.skill-task-card'),
|
||||
theme: document.documentElement.getAttribute('data-theme'),
|
||||
};
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
console.log('ERRS', errs.slice(0,6));
|
||||
await b.close();
|
||||
@@ -0,0 +1,18 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader'] });
|
||||
const p = await b.newPage();
|
||||
const errs=[]; p.on('console',m=>{ if(m.type()==='error') errs.push(m.text()); });
|
||||
p.on('pageerror',e=>errs.push('PAGEERR '+e.message));
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
const cards = await p.$$eval('#sec-contact .contact-card', els => els.map(e=>{
|
||||
const cs = getComputedStyle(e);
|
||||
const before = getComputedStyle(e,'::before');
|
||||
const img = e.querySelector('img');
|
||||
return { name:e.querySelector('.contact-card__name')?.textContent,
|
||||
boxShadow: cs.boxShadow.slice(0,40),
|
||||
beforeBg: before.backgroundImage.slice(0,60),
|
||||
borderW: cs.borderTopWidth,
|
||||
imgLoaded: img ? (img.complete && img.naturalWidth>0) : 'no-img' };
|
||||
}));
|
||||
console.log(JSON.stringify({count:cards.length, cards, errs}, null, 1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,13 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader'] });
|
||||
const p = await b.newPage();
|
||||
const errs=[]; p.on('console',m=>{ if(m.type()==='error') errs.push(m.text()); });
|
||||
p.on('pageerror',e=>errs.push('PAGEERR '+e.message));
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
// dark
|
||||
const dark = await p.$$eval('#sec-contact .contact-card', els => els.map(e=>({n:e.querySelector('.contact-card__name')?.textContent, bs:e.style.boxShadow?'inline':'', shadow:getComputedStyle(e).boxShadow.length})));
|
||||
// light theme
|
||||
await p.evaluate(()=>document.documentElement.setAttribute('data-theme','light'));
|
||||
const light = await p.$$eval('#sec-contact .contact-card', els => els.map(e=>({n:e.querySelector('.contact-card__name')?.textContent, shadow:getComputedStyle(e).boxShadow.slice(0,30)})));
|
||||
console.log(JSON.stringify({darkCount:dark.length, light, errs}, null, 1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,22 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
const errs=[]; p.on('pageerror',e=>errs.push(e.message)); p.on('console',m=>{if(m.type()==='error')errs.push(m.text());});
|
||||
await p.setViewport({width:1100,height:1400});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1500));
|
||||
const r = await p.evaluate(()=>{
|
||||
const shaderCards=[...document.querySelectorAll('.card-shader[data-shader]')];
|
||||
const mounted=shaderCards.map(w=>!!w.paperShaderMount);
|
||||
return {
|
||||
hasSecShader: !!document.querySelector('#sec-shader'),
|
||||
hasSecShaderGrid: !!document.querySelector('#sec-shader-grid'),
|
||||
hasSecContact: !!document.querySelector('#sec-contact'),
|
||||
totalShaderWraps: shaderCards.length,
|
||||
allMounted: mounted.every(Boolean),
|
||||
mountedCount: mounted.filter(Boolean).length,
|
||||
};
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
console.log('ERRS', errs.slice(0,5));
|
||||
await b.close();
|
||||
@@ -0,0 +1,23 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1280,height:1000});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
|
||||
const probe = async (sel) => p.evaluate((s)=>{
|
||||
const e = document.querySelector(s);
|
||||
const cs = getComputedStyle(e);
|
||||
const bs = cs.boxShadow.split('),').map(x=>x.trim());
|
||||
return {
|
||||
bg: cs.backgroundColor,
|
||||
boxShadow: bs,
|
||||
};
|
||||
}, sel);
|
||||
|
||||
const neu = await probe('#sec-final .neu-card');
|
||||
const cc = await probe('#sec-contact .contact-card');
|
||||
console.log('=== NEU-CARD (Финал) ===');
|
||||
console.log(JSON.stringify(neu,null,1));
|
||||
console.log('=== CONTACT-CARD ===');
|
||||
console.log(JSON.stringify(cc,null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,16 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader'] });
|
||||
const p = await b.newPage();
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
const probe = async (sel) => p.evaluate((s)=>{
|
||||
const e = document.querySelector(s); const cs=getComputedStyle(e);
|
||||
return { bg: cs.backgroundColor, bgImg: cs.backgroundImage.slice(0,55), shadow: cs.boxShadow.split('),').map(x=>x.trim().replace(/rgba\([^)]*\)/,'C')) };
|
||||
}, sel);
|
||||
console.log('DARK');
|
||||
console.log(' neu:', JSON.stringify(await probe('#sec-final .neu-card')));
|
||||
console.log(' cc :', JSON.stringify(await probe('#sec-contact .contact-card')));
|
||||
await p.evaluate(()=>document.documentElement.setAttribute('data-theme','light'));
|
||||
console.log('LIGHT');
|
||||
console.log(' neu:', JSON.stringify(await probe('#sec-final .neu-card')));
|
||||
console.log(' cc :', JSON.stringify(await probe('#sec-contact .contact-card')));
|
||||
await b.close();
|
||||
@@ -0,0 +1,11 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader'] });
|
||||
const p = await b.newPage();
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
const probe = async (sel) => p.evaluate((s)=>{
|
||||
const e = document.querySelector(s); const cs=getComputedStyle(e);
|
||||
return { bgImg: cs.backgroundImage.slice(0,60) };
|
||||
}, sel);
|
||||
console.log('DARK neu bgImg:', (await probe('#sec-final .neu-card')).bgImg);
|
||||
console.log('DARK cc bgImg:', (await probe('#sec-contact .contact-card')).bgImg);
|
||||
await b.close();
|
||||
@@ -0,0 +1,19 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader'] });
|
||||
const p = await b.newPage();
|
||||
const errs=[]; p.on('console',m=>{if(m.type()==='error')errs.push(m.text())}); p.on('pageerror',e=>errs.push('PE '+e.message));
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
const probe = async (sel) => p.evaluate((s)=>{
|
||||
const e=document.querySelector(s); const cs=getComputedStyle(e);
|
||||
return { bg: cs.backgroundColor, bgImg: cs.backgroundImage.slice(0,45), shadowLen: cs.boxShadow.length,
|
||||
dir: cs.flexDirection, pad: cs.paddingTop };
|
||||
}, sel);
|
||||
const neu = await probe('#sec-final .neu-card');
|
||||
const cc = await probe('#sec-contact .contact-card');
|
||||
const neuShadow = await p.evaluate(()=>getComputedStyle(document.querySelector('#sec-final .neu-card')).boxShadow);
|
||||
const ccShadow = await p.evaluate(()=>getComputedStyle(document.querySelector('#sec-contact .contact-card')).boxShadow);
|
||||
console.log('neu:', JSON.stringify(neu));
|
||||
console.log('cc :', JSON.stringify(cc));
|
||||
console.log('shadows equal:', neuShadow===ccShadow);
|
||||
console.log('errs:', errs);
|
||||
await b.close();
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
const logs=[];
|
||||
p.on('console', m=>logs.push('['+m.type()+'] '+m.text()));
|
||||
p.on('pageerror', e=>logs.push('[pageerror] '+e.message));
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,800));
|
||||
const r = await p.evaluate(async ()=>{
|
||||
const mod = await import('/vendor/paper-shaders/index.js');
|
||||
const { ShaderMount, meshGradientFragmentShader, getShaderColorFromString } = mod;
|
||||
const host = document.createElement('div'); host.style.cssText='width:300px;height:200px;position:relative';
|
||||
document.body.appendChild(host);
|
||||
const colors = ['#7c5cff','#00c2c7','#ff5c8a','#ffb347'].map(getShaderColorFromString);
|
||||
const uniforms = { u_colors: colors, u_colorsCount: colors.length, u_distortion:1.2, u_swirl:0.8, u_grainMixer:0.08, u_grainOverlay:0.04 };
|
||||
const m = new ShaderMount(host, meshGradientFragmentShader, uniforms, { preserveDrawingBuffer:true, antialias:true }, 1.0);
|
||||
return { keys: Object.keys(m.uniformLocations), uColorsLoc: m.uniformLocations.u_colors, uColorsCountLoc: m.uniformLocations.u_colorsCount };
|
||||
});
|
||||
console.log('RESULT', JSON.stringify(r));
|
||||
console.log('LOGS:\n'+logs.join('\n'));
|
||||
await b.close();
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,800));
|
||||
const r = await p.evaluate(async ()=>{
|
||||
const mod = await import('/vendor/paper-shaders/index.js');
|
||||
const { ShaderMount, meshGradientFragmentShader, getShaderColorFromString } = mod;
|
||||
const host = document.createElement('div'); host.style.cssText='width:300px;height:200px;position:relative';
|
||||
document.body.appendChild(host);
|
||||
const colors = ['#7c5cff','#00c2c7','#ff5c8a','#ffb347'].map(getShaderColorFromString);
|
||||
const m = new ShaderMount(host, meshGradientFragmentShader, { u_colors: colors, u_colorsCount: colors.length, u_distortion:1.2, u_swirl:0.8, u_grainMixer:0.08, u_grainOverlay:0.04 }, { preserveDrawingBuffer:true, antialias:true }, 1.0);
|
||||
const gl=m.gl, pr=m.program;
|
||||
// правильное чтение: getUniform ВОЗВРАЩАЕТ значение
|
||||
const gf=(n)=>gl.getUniform(pr, gl.getUniformLocation(pr,n));
|
||||
const colorsWritten = gf('u_colors[0]'); // Float32Array(4)
|
||||
const countWritten = gf('u_colorsCount'); // number
|
||||
const swirlWritten = gf('u_swirl');
|
||||
// readPixels скан
|
||||
m.render(performance.now()); m.render(performance.now());
|
||||
const W=m.canvasElement.width,H=m.canvasElement.height; const buf=new Uint8Array(W*H*4); gl.readPixels(0,0,W,H,gl.RGBA,gl.UNSIGNED_BYTE,buf);
|
||||
let bright=0,maxc=0; for(let i=0;i<buf.length;i+=4){const mx=Math.max(buf[i],buf[i+1],buf[i+2]); if(mx>120)bright++; maxc=Math.max(maxc,mx);}
|
||||
return {
|
||||
u_colors0: colorsWritten ? Array.from(colorsWritten).map(x=>+x.toFixed(2)) : null,
|
||||
u_colorsCount: countWritten,
|
||||
u_swirl: swirlWritten,
|
||||
brightPixels: bright, maxChannel: maxc,
|
||||
};
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,25 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,800));
|
||||
const r = await p.evaluate(async ()=>{
|
||||
const mod = await import('/vendor/paper-shaders/index.js');
|
||||
const { ShaderMount, meshGradientFragmentShader, getShaderColorFromString } = mod;
|
||||
const host = document.createElement('div'); host.style.cssText='width:300px;height:200px;position:relative';
|
||||
document.body.appendChild(host);
|
||||
const colors = ['#7c5cff','#00c2c7','#ff5c8a','#ffb347'].map(getShaderColorFromString);
|
||||
const uniforms = { u_colors: colors, u_colorsCount: colors.length, u_distortion:1.2, u_swirl:0.8, u_grainMixer:0.08, u_grainOverlay:0.04 };
|
||||
console.log('uniforms passed:', JSON.stringify(uniforms.u_colors), 'count', uniforms.u_colorsCount);
|
||||
const m = new ShaderMount(host, meshGradientFragmentShader, uniforms, { preserveDrawingBuffer:true, antialias:true }, 1.0);
|
||||
m.render(performance.now()); m.render(performance.now());
|
||||
const gl=m.gl;
|
||||
const cnt=new Float32Array(1); gl.getUniform(m.program, gl.getUniformLocation(m.program,'u_colorsCount'), cnt);
|
||||
const c0=new Float32Array(4); gl.getUniform(m.program, gl.getUniformLocation(m.program,'u_colors[0]'), c0);
|
||||
const W=m.canvasElement.width,H=m.canvasElement.height; const buf=new Uint8Array(W*H*4); gl.readPixels(0,0,W,H,gl.RGBA,gl.UNSIGNED_BYTE,buf);
|
||||
let bright=0,maxc=0; for(let i=0;i<buf.length;i+=4){const mx=Math.max(buf[i],buf[i+1],buf[i+2]); if(mx>120)bright++; maxc=Math.max(maxc,mx);}
|
||||
return { count:cnt[0], c0:Array.from(c0).map(x=>+x.toFixed(2)), bright, maxc };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
import sharp from 'sharp';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1280,height:1200});
|
||||
const errs=[]; p.on('console',m=>{if(m.type()==='error')errs.push(m.text())}); p.on('pageerror',e=>errs.push('PE '+e.message));
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const demo = await p.$('[data-shader-demo]');
|
||||
await demo.evaluate(el=>el.scrollIntoView({block:'center'}));
|
||||
await new Promise(r=>setTimeout(r,400));
|
||||
async function probe(key){
|
||||
if(key){ await p.click(`[data-shader-switch="${key}"]`); await new Promise(r=>setTimeout(r,700)); }
|
||||
const el = await p.$('[data-shader-demo]');
|
||||
const box = await el.boundingBox();
|
||||
await el.screenshot({path:'/tmp/demo.png'});
|
||||
const {data,info}=await sharp('/tmp/demo.png').raw().toBuffer({resolveWithObject:true});
|
||||
let n=info.width*info.height, rs=0,gs=0,bs=0; const cols=new Set();
|
||||
for(let i=0;i<data.length;i+=3){ rs+=data[i];gs+=data[i+1];bs+=data[i+2]; if(i%1500===0) cols.add(`${data[i]>>5},${data[i+1]>>5},${data[i+2]>>5}`); }
|
||||
return { key: key||'mesh', avg:[Math.round(rs/n),Math.round(gs/n),Math.round(bs/n)], distinct: cols.size };
|
||||
}
|
||||
const r1=await probe(); const r2=await probe('grain'); const r3=await probe('voronoi'); const r4=await probe('staticMesh');
|
||||
console.log(JSON.stringify({r1,r2,r3,r4,errs},null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,21 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
import sharp from 'sharp';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1500));
|
||||
await p.evaluate(()=>document.querySelector('#sec-shader').scrollIntoView());
|
||||
await new Promise(r=>setTimeout(r,900));
|
||||
// координаты демо-карточки
|
||||
const rect = await p.evaluate(()=>{ const r=document.querySelector('[data-shader-demo]').getBoundingClientRect(); return {x:r.x,y:r.y,w:r.width,h:r.height}; });
|
||||
await p.screenshot({path:'/tmp/full.png'});
|
||||
const img = sharp('/tmp/full.png');
|
||||
const {data,info}=await img.raw().toBuffer({resolveWithObject:true});
|
||||
// вырежем центр демо-карточки (по координатам вьюпорта)
|
||||
const x0=Math.floor(rect.x+rect.w*0.2), y0=Math.floor(rect.y+rect.h*0.2);
|
||||
const x1=Math.floor(rect.x+rect.w*0.8), y1=Math.floor(rect.y+rect.h*0.8);
|
||||
let rs=0,gs=0,bs=0,n=0; const cols=new Set();
|
||||
for(let y=y0;y<y1;y+=3){ for(let x=x0;x<x1;x+=3){ const i=(y*info.width+x)*3; rs+=data[i];gs+=data[i+1];bs+=data[i+2]; cols.add(`${data[i]>>5},${data[i+1]>>5},${data[i+2]>>5}`); n++; } }
|
||||
console.log('demo card region avg:', [Math.round(rs/n),Math.round(gs/n),Math.round(bs/n)], 'distinct coarse colors:', cols.size);
|
||||
await b.close();
|
||||
@@ -0,0 +1,34 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
import sharp from 'sharp';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
await p.evaluate(()=>document.querySelector('#sec-shader').scrollIntoView());
|
||||
await new Promise(r=>setTimeout(r,600));
|
||||
async function probe(key){
|
||||
if(key){ await p.click(`[data-shader-switch="${key}"]`); await new Promise(r=>setTimeout(r,900)); }
|
||||
// снимок canvas напрямую через toDataURL -> png
|
||||
const dataUrl = await p.evaluate(()=>{
|
||||
const cv=document.querySelector('[data-shader-demo] canvas');
|
||||
if(!cv) return null;
|
||||
try { return cv.toDataURL('image/png').slice(0,30); } catch(e){ return 'ERR '+e.message; }
|
||||
});
|
||||
const buf = await p.evaluate(()=>{
|
||||
const cv=document.querySelector('[data-shader-demo] canvas');
|
||||
return cv ? cv.toDataURL('image/png') : null;
|
||||
});
|
||||
let distinct=0, avg=[0,0,0];
|
||||
if(buf){ const b64=buf.split(',')[1]; const {data,info}=await sharp(Buffer.from(b64,'base64')).raw().toBuffer({resolveWithObject:true});
|
||||
let n=info.width*info.height,rs=0,gs=0,bs=0; const cols=new Set();
|
||||
for(let i=0;i<data.length;i+=4){ rs+=data[i];gs+=data[i+1];bs+=data[i+2];
|
||||
if(i%2000===0) cols.add(`${data[i]>>5},${data[i+1]>>5},${data[i+2]>>5}`); }
|
||||
avg=[Math.round(rs/n),Math.round(gs/n),Math.round(bs/n)]; distinct=cols.size; }
|
||||
return { key:key||'mesh', dataUrlHead:dataUrl, avg, distinct };
|
||||
}
|
||||
console.log(JSON.stringify(await probe(),null,0));
|
||||
console.log(JSON.stringify(await probe('grain'),null,0));
|
||||
console.log(JSON.stringify(await probe('voronoi'),null,0));
|
||||
console.log(JSON.stringify(await probe('staticMesh'),null,0));
|
||||
await b.close();
|
||||
@@ -0,0 +1,20 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
import sharp from 'sharp';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
// прокрутим ровно к карточке через window.scrollTo по абсолютному смещению
|
||||
const top = await p.evaluate(()=>{ const r=document.querySelector('[data-shader-demo]').getBoundingClientRect(); return r.top+window.scrollY; });
|
||||
await p.evaluate((t)=>window.scrollTo(0, t-200), top);
|
||||
await new Promise(r=>setTimeout(r,900));
|
||||
await p.screenshot({path:'/tmp/full2.png'});
|
||||
const {data,info}=await sharp('/tmp/full2.png').raw().toBuffer({resolveWithObject:true});
|
||||
const rect = await p.evaluate(()=>{ const r=document.querySelector('[data-shader-demo]').getBoundingClientRect(); return {x:r.x,y:r.y,w:r.width,h:r.height}; });
|
||||
const x0=Math.max(0,Math.floor(rect.x+20)), y0=Math.max(0,Math.floor(rect.y+20));
|
||||
const x1=Math.min(info.width,Math.floor(rect.x+rect.w-20)), y1=Math.min(info.height,Math.floor(rect.y+rect.h-20));
|
||||
let rs=0,gs=0,bs=0,n=0; const cols=new Set();
|
||||
if(x1>x0&&y1>y0){ for(let y=y0;y<y1;y+=2){ for(let x=x0;x<x1;x+=2){ const i=(y*info.width+x)*3; rs+=data[i];gs+=data[i+1];bs+=data[i+2]; cols.add(`${data[i]>>5},${data[i+1]>>5},${data[i+2]>>5}`); n++; } } }
|
||||
console.log('region avg', n?[Math.round(rs/n),Math.round(gs/n),Math.round(bs/n)]:'empty', 'distinct', cols.size, 'rect', rect, 'imgsize', info.width+'x'+info.height);
|
||||
await b.close();
|
||||
@@ -0,0 +1,21 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
import sharp from 'sharp';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1500));
|
||||
async function probe(key){
|
||||
if(key){ await p.click(`[data-shader-switch="${key}"]`); await new Promise(r=>setTimeout(r,1000)); }
|
||||
const el = await p.$('[data-shader-demo]');
|
||||
await el.screenshot({path:'/tmp/demo.png'});
|
||||
const {data,info}=await sharp('/tmp/demo.png').raw().toBuffer({resolveWithObject:true});
|
||||
let n=info.width*info.height,rs=0,gs=0,bs=0; const cols=new Set();
|
||||
for(let i=0;i<data.length;i+=3){ rs+=data[i];gs+=data[i+1];bs+=data[i+2]; if(i%2000===0) cols.add(`${data[i]>>5},${data[i+1]>>5},${data[i+2]>>5}`); }
|
||||
return { key:key||'mesh', avg:[Math.round(rs/n),Math.round(gs/n),Math.round(bs/n)], distinct:cols.size };
|
||||
}
|
||||
console.log(JSON.stringify(await probe()));
|
||||
console.log(JSON.stringify(await probe('grain')));
|
||||
console.log(JSON.stringify(await probe('voronoi')));
|
||||
console.log(JSON.stringify(await probe('staticMesh')));
|
||||
await b.close();
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
import sharp from 'sharp';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
const errs=[]; p.on('console',m=>{if(m.type()==='error')errs.push(m.text())}); p.on('pageerror',e=>errs.push('PE '+e.message));
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
await p.evaluate(()=>document.querySelector('#sec-shader').scrollIntoView());
|
||||
await new Promise(r=>setTimeout(r,700));
|
||||
async function probe(key){
|
||||
if(key){ await p.click(`[data-shader-switch="${key}"]`); await new Promise(r=>setTimeout(r,900)); }
|
||||
const buf = await p.evaluate(()=>{ const cv=document.querySelector('[data-shader-demo] canvas'); return cv?cv.toDataURL('image/png'):null; });
|
||||
let avg=[0,0,0], distinct=0;
|
||||
if(buf){ const {data,info}=await sharp(Buffer.from(buf.split(',')[1],'base64')).raw().toBuffer({resolveWithObject:true});
|
||||
let n=info.width*info.height,rs=0,gs=0,bs=0; const cols=new Set();
|
||||
for(let i=0;i<data.length;i+=4){ rs+=data[i];gs+=data[i+1];bs+=data[i+2]; if(i%1500===0) cols.add(`${data[i]>>5},${data[i+1]>>5},${data[i+2]>>5}`); }
|
||||
avg=[Math.round(rs/n),Math.round(gs/n),Math.round(bs/n)]; distinct=cols.size; }
|
||||
return { key:key||'mesh', avg, distinct, hasCanvas:!!buf };
|
||||
}
|
||||
console.log(JSON.stringify(await probe(),null,0));
|
||||
console.log(JSON.stringify(await probe('grain'),null,0));
|
||||
console.log(JSON.stringify(await probe('voronoi'),null,0));
|
||||
console.log(JSON.stringify(await probe('staticMesh'),null,0));
|
||||
console.log('errs:', errs);
|
||||
await b.close();
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300,deviceScaleFactor:1});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1500));
|
||||
await p.evaluate(()=>document.querySelector('#sec-shader').scrollIntoView());
|
||||
await new Promise(r=>setTimeout(r,800));
|
||||
await p.screenshot({path:'/tmp/sec-shader.png'});
|
||||
console.log('saved');
|
||||
await b.close();
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1280,height:1200});
|
||||
const errs=[]; p.on('console',m=>{if(m.type()==='error')errs.push(m.text())}); p.on('pageerror',e=>errs.push('PE '+e.message));
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1000));
|
||||
await p.evaluate(()=>document.querySelector('[data-shader-demo]').scrollIntoView({block:'center'}));
|
||||
await new Promise(r=>setTimeout(r,500));
|
||||
async function probe(key){
|
||||
if(key){ await p.click(`[data-shader-switch="${key}"]`); await new Promise(r=>setTimeout(r,800)); }
|
||||
return await p.evaluate(()=>{
|
||||
const el=document.querySelector('[data-shader-demo]');
|
||||
const cv=el.querySelector('canvas');
|
||||
if(!cv) return {canvas:false};
|
||||
const gl=cv.getContext('webgl2')||cv.getContext('webgl');
|
||||
const px=new Uint8Array(4);
|
||||
// читаем угол (0,0) — там обычно цвет градиента
|
||||
gl.readPixels(2,2,1,1,gl.RGBA,gl.UNSIGNED_BYTE,px);
|
||||
return { canvas:true, w:cv.width, h:cv.height, corner:Array.from(px), key: el.dataset.shaderKey };
|
||||
});
|
||||
}
|
||||
console.log('mesh:', JSON.stringify(await probe()));
|
||||
console.log('grain:', JSON.stringify(await probe('grain')));
|
||||
console.log('voronoi:', JSON.stringify(await probe('voronoi')));
|
||||
console.log('staticMesh:', JSON.stringify(await probe('staticMesh')));
|
||||
console.log('errs:', errs);
|
||||
await b.close();
|
||||
@@ -0,0 +1,30 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
const errs=[]; p.on('console',m=>{ if(m.type()==='error'||m.type()==='warning') errs.push(m.type()+': '+m.text()); });
|
||||
p.on('pageerror',e=>errs.push('PAGEERR: '+e.message));
|
||||
p.on('requestfailed',r=>errs.push('REQFAIL: '+r.url()+' '+r.failure()?.errorText));
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1500));
|
||||
const diag = await p.evaluate(()=>{
|
||||
const sec=document.querySelector('#sec-shader');
|
||||
const demo=document.querySelector('[data-shader-demo]');
|
||||
const canvas=document.querySelector('#sec-shader canvas');
|
||||
const sw=document.querySelectorAll('[data-shader-switch]').length;
|
||||
return {
|
||||
secExists: !!sec,
|
||||
secH: sec?Math.round(sec.getBoundingClientRect().height):0,
|
||||
demoExists: !!demo,
|
||||
demoH: demo?Math.round(demo.getBoundingClientRect().height):0,
|
||||
canvasCount: document.querySelectorAll('#sec-shader canvas').length,
|
||||
swCount: sw,
|
||||
swVisible: sw?getComputedStyle(document.querySelector('[data-shader-switch]')).display:'n/a',
|
||||
};
|
||||
});
|
||||
// проверим доступен ли модуль
|
||||
const modOk = await p.evaluate(async()=>{
|
||||
try { const m = await import('/vendor/paper-shaders/index.js'); return 'OK keys:'+Object.keys(m).length; }
|
||||
catch(e){ return 'IMPORT ERR: '+e.message; }
|
||||
});
|
||||
console.log(JSON.stringify({diag, modOk, errs: errs.slice(0,10)}, null, 1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,21 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const r = await p.evaluate(()=>{
|
||||
const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount;
|
||||
const gl=m.gl;
|
||||
// два render (drawArrays инициализируется лениво на 1-м)
|
||||
m.render(performance.now()); m.render(performance.now());
|
||||
const W=m.canvasElement.width, H=m.canvasElement.height;
|
||||
const buf=new Uint8Array(W*H*4); gl.readPixels(0,0,W,H,gl.RGBA,gl.UNSIGNED_BYTE,buf);
|
||||
let bright=0, maxc=0;
|
||||
for(let i=0;i<buf.length;i+=4){ const r=buf[i],g=buf[i+1],bl=buf[i+2]; const mx=Math.max(r,g,bl); if(mx>120) bright++; maxc=Math.max(maxc,mx); }
|
||||
const cntLoc=gl.getUniformLocation(m.program,'u_colorsCount'); const cv=new Float32Array(1); gl.getUniform(m.program,cntLoc,cv);
|
||||
const c0=new Float32Array(4); gl.getUniform(m.program,gl.getUniformLocation(m.program,'u_colors[0]'),c0);
|
||||
return { brightPixels: bright, maxChannel: maxc, uColorsCountFloat: cv[0], uColor0: Array.from(c0).map(x=>+x.toFixed(2)) };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,16 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
const errs=[];
|
||||
p.on('pageerror', e=>errs.push('PE '+e.message));
|
||||
p.on('console', m=>{ if(m.type()==='error') errs.push('CE '+m.text()); });
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const r = await p.evaluate(()=>{
|
||||
const m=document.querySelector('[data-shader-demo] .card-shader')?.paperShaderMount;
|
||||
return { hasMount: !!m, speed: m?.currentSpeed, isVp: m?.isInViewport };
|
||||
});
|
||||
console.log('MOUNT', JSON.stringify(r));
|
||||
console.log('ERRS', errs.slice(0,5));
|
||||
await b.close();
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
const errs=[];
|
||||
p.on('pageerror', e=>errs.push('PE '+e.message));
|
||||
p.on('console', m=>{ if(m.type()==='error') errs.push('CE '+m.text()); });
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1000));
|
||||
const a = await p.evaluate(()=>{ const m=document.querySelector('[data-shader-demo] .card-shader')?.paperShaderMount; return m?{speed:m.currentSpeed,frame:m.getCurrentFrame(),inVp:m.isInViewport}:null; });
|
||||
await new Promise(r=>setTimeout(r,2000));
|
||||
const c = await p.evaluate(()=>{ const m=document.querySelector('[data-shader-demo] .card-shader')?.paperShaderMount; return m?{speed:m.currentSpeed,frame:m.getCurrentFrame(),inVp:m.isInViewport}:null; });
|
||||
console.log('A',JSON.stringify(a),'C',JSON.stringify(c));
|
||||
console.log('ANIMATING:', c && a && c.frame>a.frame && c.speed>0);
|
||||
console.log('ERRS', errs.slice(0,5));
|
||||
await b.close();
|
||||
@@ -0,0 +1,12 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,800)); // просто ждём, НЕ скроллим к секции
|
||||
const a = await p.evaluate(()=>{ const m=document.querySelector('[data-shader-demo] .card-shader')?.paperShaderMount; return m?{frame:m.getCurrentFrame(),speed:m.currentSpeed,inVp:m.isInViewport}:null; });
|
||||
await new Promise(r=>setTimeout(r,2000));
|
||||
const c = await p.evaluate(()=>{ const m=document.querySelector('[data-shader-demo] .card-shader')?.paperShaderMount; return m?{frame:m.getCurrentFrame(),speed:m.currentSpeed,inVp:m.isInViewport}:null; });
|
||||
console.log('A',JSON.stringify(a)); console.log('C',JSON.stringify(c));
|
||||
console.log('ANIMATING:', !!c && c.frame>a.frame && c.speed>0);
|
||||
await b.close();
|
||||
@@ -0,0 +1,20 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
await p.evaluate(()=>document.querySelector('[data-shader-demo]').scrollIntoView({block:'center'}));
|
||||
await new Promise(r=>setTimeout(r,500));
|
||||
// достанем mount через глобальный хук: ShaderMount сохраняет себя в parentElement.paperShaderMount
|
||||
const r = await p.evaluate(async()=>{
|
||||
const wrap=document.querySelector('[data-shader-demo] .card-shader');
|
||||
const m=wrap.paperShaderMount;
|
||||
if(!m) return {hasMount:false};
|
||||
const f1=m.getCurrentFrame();
|
||||
await new Promise(r=>setTimeout(r,600));
|
||||
const f2=m.getCurrentFrame();
|
||||
return { hasMount:true, frame1:f1, frame2:f2, rafRunning: f2>f1, speed: m.speed, inViewport: m.isInViewport, currentSpeed: m.currentSpeed };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,19 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,800));
|
||||
const r = await p.evaluate(()=>{
|
||||
const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount;
|
||||
const gl=m.gl;
|
||||
const errs=[];
|
||||
// проверим статус программы и шейдеров
|
||||
const vs = gl.getProgramParameter(m.program, gl.LINK_STATUS);
|
||||
// проверим, залит ли canvas хоть чем-то: clearColor потом readPixels
|
||||
gl.clearColor(1,0,0,1); gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
const px=new Uint8Array(4); gl.readPixels(10,10,1,1,gl.RGBA,gl.UNSIGNED_BYTE,px);
|
||||
return { linkStatus: vs, afterClearRed: Array.from(px), glError: gl.getError() };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const r = await p.evaluate(()=>{
|
||||
const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount;
|
||||
const gl=m.gl;
|
||||
gl.getError(); // сброс
|
||||
m.render(performance.now());
|
||||
const e = gl.getError();
|
||||
const px=new Uint8Array(4); gl.readPixels(360,220,1,1,gl.RGBA,gl.UNSIGNED_BYTE,px);
|
||||
// проверим a_position location
|
||||
const aLoc = gl.getAttribLocation(m.program, 'a_position');
|
||||
return { glErrorAfterRender: e, centerPx: Array.from(px), aPosLoc: aLoc, clearC: (()=>{const c=new Float32Array(4); gl.getClearColor?.(c); return Array.from(c);})() };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,24 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const r = await p.evaluate(()=>{
|
||||
const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount;
|
||||
const gl=m.gl;
|
||||
const flat=[0.486,0.361,1,1, 0,0.761,0.78,1, 1,0.361,0.541,1, 1,0.702,0.278,1];
|
||||
gl.useProgram(m.program);
|
||||
gl.uniform4fv(gl.getUniformLocation(m.program,'u_colors'), new Float32Array(flat));
|
||||
gl.uniform1f(gl.getUniformLocation(m.program,'u_colorsCount'),4);
|
||||
gl.drawArrays(gl.TRIANGLES,0,6);
|
||||
const W=m.canvasElement.width,H=m.canvasElement.height;
|
||||
const pts=[[100,100],[360,100],[620,100],[100,220],[360,220],[620,220],[100,340],[360,340],[620,340]];
|
||||
const out=pts.map(([x,y])=>{const px=new Uint8Array(4);gl.readPixels(x,y,1,1,gl.RGBA,gl.UNSIGNED_BYTE,px);return [x,y,Array.from(px)];});
|
||||
// макс яркость по всему canvas
|
||||
const buf=new Uint8Array(W*H*4); gl.readPixels(0,0,W,H,gl.RGBA,gl.UNSIGNED_BYTE,buf);
|
||||
let maxc=0; for(let i=0;i<buf.length;i++) maxc=Math.max(maxc,buf[i]);
|
||||
return { samples:out, maxChannel:maxc };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,17 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const r = await p.evaluate(()=>{
|
||||
const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount;
|
||||
const keys=['u_time','u_colors','u_colorsCount','u_distortion','u_swirl','u_grainMixer','u_grainOverlay'];
|
||||
const out={};
|
||||
keys.forEach(k=>{ const l=m.uniformLocations[k]; out[k]= l===null?'NULL':(l===undefined?'UNDEF':typeof l); });
|
||||
// также посмотрим this.providedUniforms
|
||||
const pu = m.providedUniforms ? Object.keys(m.providedUniforms) : 'none';
|
||||
return { locations: out, providedKeys: pu };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const r = await p.evaluate(()=>{
|
||||
const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount;
|
||||
const gl=m.gl;
|
||||
const loc0 = gl.getUniformLocation(m.program, 'u_colors');
|
||||
const locB = gl.getUniformLocation(m.program, 'u_colors[0]');
|
||||
// вручную зададим 4 цвета vec4
|
||||
const flat = [0.486,0.361,1,1, 0,0.761,0.78,1, 1,0.361,0.541,1, 1,0.702,0.278,1];
|
||||
gl.useProgram(m.program);
|
||||
if (loc0) gl.uniform4fv(loc0, flat); else if (locB) gl.uniform4fv(locB, flat);
|
||||
gl.drawArrays(gl.TRIANGLES,0,6);
|
||||
const px=new Uint8Array(4); gl.readPixels(360,220,1,1,gl.RGBA,gl.UNSIGNED_BYTE,px);
|
||||
return { loc0null: loc0===null, locBnull: locB===null, centerAfterManual: Array.from(px) };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
const errs=[]; p.on('pageerror',e=>errs.push(e.message)); p.on('console',m=>{if(m.type()==='error')errs.push(m.text());});
|
||||
await p.setViewport({width:1100,height:1400});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1500));
|
||||
await p.evaluate(()=>document.querySelector('#sec-shader-grid')?.scrollIntoView());
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const r = await p.evaluate(()=>{
|
||||
const cards=[...document.querySelectorAll('#sec-shader-grid .neu-card--shader')];
|
||||
const info=cards.map(c=>{
|
||||
const sh=c.querySelector('.card-shader');
|
||||
const m=sh?.paperShaderMount;
|
||||
const cs=getComputedStyle(c);
|
||||
const beforeZ=getComputedStyle(c,'::before').zIndex;
|
||||
return { hasShaderWrap:!!sh, mounted:!!m, speed:m?.currentSpeed, frame:m?Math.round(m.getCurrentFrame()):null, bg:cs.backgroundColor, beforeZ };
|
||||
});
|
||||
return { count: cards.length, info };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
console.log('ERRS', errs.slice(0,5));
|
||||
await b.close();
|
||||
@@ -0,0 +1,18 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
const errs=[]; p.on('pageerror',e=>errs.push(e.message)); p.on('console',m=>{if(m.type()==='error')errs.push(m.text());});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1500));
|
||||
await p.evaluate(()=>document.querySelector('#sec-all-shaders')?.scrollIntoView());
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const r = await p.evaluate(()=>{
|
||||
const cards=[...document.querySelectorAll('.card-shader[data-shader]')];
|
||||
const info=cards.map(c=>({brand:c.dataset.shader, mounted:!!c.paperShaderMount, frag:c.paperShaderMount?.fragmentShader?.name||null}));
|
||||
const f0=cards.find(c=>c.dataset.shader==='demo')?.paperShaderMount;
|
||||
return { count: cards.length, info, demoFrame: f0?Math.round(f0.getCurrentFrame()):null,
|
||||
demoAnimated: f0? (f0.getCurrentFrame()*0+ (f0.currentSpeed>0)) : null };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
console.log('ERRS', errs.slice(0,6));
|
||||
await b.close();
|
||||
@@ -0,0 +1,12 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
const errs=[]; p.on('pageerror',e=>errs.push('PE: '+e.message)); p.on('console',m=>{if(m.type()==='error')errs.push('CON: '+m.text());});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1500));
|
||||
const r = await p.evaluate(()=>{
|
||||
const wrap=document.querySelector('[data-shader-demo] .card-shader');
|
||||
return { hasMount: !!wrap?.paperShaderMount, scriptLoaded: !!window.__mountLabShaders };
|
||||
});
|
||||
console.log(JSON.stringify({r, errs}, null, 1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,20 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
await p.evaluate(()=>document.querySelector('[data-shader-demo]').scrollIntoView({block:'center'}));
|
||||
await new Promise(r=>setTimeout(r,500));
|
||||
const r = await p.evaluate(()=>{
|
||||
const wrap=document.querySelector('[data-shader-demo] .card-shader');
|
||||
const m=wrap.paperShaderMount; const cv=wrap.querySelector('canvas');
|
||||
const gl=cv.getContext('webgl2',{preserveDrawingBuffer:true})||cv.getContext('webgl',{preserveDrawingBuffer:true});
|
||||
const read=()=>{ const a=new Uint8Array(4); gl.readPixels(cv.width/2|0,cv.height/2|0,1,1,gl.RGBA,gl.UNSIGNED_BYTE,a); return Array.from(a); };
|
||||
m.render(0); const t0=read();
|
||||
m.render(3000); const t1=read();
|
||||
m.render(8000); const t2=read();
|
||||
return { t0, t1, t2 };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,26 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
const errs=[],warns=[];
|
||||
p.on('pageerror', e=>errs.push('PE '+e.message));
|
||||
p.on('requestfailed', r=>errs.push('REQFAIL '+r.url()+' '+r.failure()?.errorText));
|
||||
p.on('console', m=>{ const t=m.type(); if(t==='error') errs.push('CE '+m.text()); if(t==='warning') warns.push('W '+m.text()); });
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'networkidle2',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1500));
|
||||
const info = await p.evaluate(()=>{
|
||||
const cs=document.querySelector('[data-shader-demo] .card-shader');
|
||||
const m=cs?.paperShaderMount;
|
||||
const bg=getComputedStyle(cs).backgroundColor;
|
||||
const canvas=cs?.querySelector('canvas');
|
||||
return {
|
||||
hasWrap: !!cs, hasMount: !!m,
|
||||
wrapBg: bg, hasCanvas: !!canvas,
|
||||
canvasW: canvas?.width, canvasH: canvas?.height,
|
||||
speed: m?.currentSpeed, frame: m?Math.round(m.getCurrentFrame()):null,
|
||||
};
|
||||
});
|
||||
console.log('INFO', JSON.stringify(info,null,1));
|
||||
console.log('ERRS', errs.slice(0,8));
|
||||
console.log('WARNS', warns.slice(0,8));
|
||||
await b.close();
|
||||
@@ -0,0 +1,52 @@
|
||||
const puppeteer = require('puppeteer');
|
||||
|
||||
async function probePage(browser, url, width) {
|
||||
const page = await browser.newPage();
|
||||
await page.setViewport({ width, height: 900, deviceScaleFactor: 1 });
|
||||
await page.goto(url, { waitUntil: 'networkidle0' });
|
||||
await page.waitForSelector('[data-mini-projects-list] .mini-projects-grid__item', { timeout: 15000 }).catch(()=>{});
|
||||
await new Promise(r => setTimeout(r, 700));
|
||||
const data = await page.evaluate(() => {
|
||||
const list = document.querySelector('[data-mini-projects-list]');
|
||||
if (!list) return { none: true };
|
||||
const inner = list.closest('.section__inner');
|
||||
const items = [...list.querySelectorAll('.mini-projects-grid__item')].filter(i => !i.hidden);
|
||||
const rowCells = (() => {
|
||||
const w = list.clientWidth;
|
||||
if (w >= 1180) return 6;
|
||||
if (w >= 880) return 4;
|
||||
if (w >= 520) return 2;
|
||||
return 1;
|
||||
})();
|
||||
return {
|
||||
listWidth: list.clientWidth,
|
||||
innerWidth: inner ? inner.clientWidth : null,
|
||||
rowCells,
|
||||
itemCount: items.length,
|
||||
items: items.map(i => ({
|
||||
cells: i.getAttribute('data-mp-cells'),
|
||||
styleW: i.style.width,
|
||||
x: i.style.transform,
|
||||
})),
|
||||
};
|
||||
});
|
||||
await page.close();
|
||||
return data;
|
||||
}
|
||||
|
||||
(async () => {
|
||||
const browser = await puppeteer.launch({ headless: 'new', args: ['--no-sandbox','--disable-setuid-sandbox'] });
|
||||
const widths = [600, 760, 900, 1024, 1180, 1278, 1356, 1600];
|
||||
const caseUrl = 'http://localhost:4175/cases/ai-platform-primo-rpa/';
|
||||
const homeUrl = 'http://localhost:4175/';
|
||||
for (const w of widths) {
|
||||
const c = await probePage(browser, caseUrl, w);
|
||||
console.log(`CASE vw=${w} inner=${c.innerWidth} rowCells=${c.rowCells} items=${c.itemCount} ` + JSON.stringify(c.items));
|
||||
}
|
||||
console.log('---');
|
||||
for (const w of widths) {
|
||||
const h = await probePage(browser, homeUrl, w);
|
||||
console.log(`HOME vw=${w} inner=${h.innerWidth} rowCells=${h.rowCells} items=${h.itemCount} ` + JSON.stringify(h.items));
|
||||
}
|
||||
await browser.close();
|
||||
})().catch(e => { console.error(e); process.exit(1); });
|
||||
@@ -104,7 +104,7 @@
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<body class="home">
|
||||
<div class="page-mesh-bg" aria-hidden="true"></div>
|
||||
<a class="skip-link" href="#main">Skip to main content</a>
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
const errs=[]; p.on('pageerror',e=>errs.push(e.message)); p.on('console',m=>{if(m.type()==='error')errs.push(m.text());});
|
||||
await p.setViewport({width:1100,height:1500});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1500));
|
||||
await p.evaluate(()=>document.querySelector('#sec-all-shaders')?.scrollIntoView());
|
||||
await new Promise(r=>setTimeout(r,1500));
|
||||
const r = await p.evaluate(()=>{
|
||||
const cells=[...document.querySelectorAll('[data-shader-cell="pulsingBorder"]')];
|
||||
const info=cells.map(c=>{const m=c.querySelector('.card-shader')?.paperShaderMount; return {mounted:!!m, speed:m?.currentSpeed, frame:m?Math.round(m.getCurrentFrame()):null};});
|
||||
// проверим, что noise-текстура задалась
|
||||
const m0=cells[0]?.querySelector('.card-shader')?.paperShaderMount;
|
||||
const texLoc=m0?m0.gl.getUniform(m0.program, m0.gl.getUniformLocation(m0.program,'u_noiseTexture')):null;
|
||||
return { cellCount: cells.length, info, noiseTexSet: texLoc!==null && texLoc!==undefined };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
console.log('ERRS', errs.slice(0,8));
|
||||
await b.close();
|
||||
@@ -0,0 +1,14 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1000));
|
||||
await p.evaluate(()=>document.querySelector('[data-shader-demo]').scrollIntoView({block:'center'}));
|
||||
await new Promise(r=>setTimeout(r,500));
|
||||
const a = await p.evaluate(()=>{ const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount; return {frame:m.getCurrentFrame(), speed:m.currentSpeed, inVp:m.isInViewport, cs:m.currentSpeed}; });
|
||||
await new Promise(r=>setTimeout(r,2000));
|
||||
const c = await p.evaluate(()=>{ const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount; return {frame:m.getCurrentFrame(), speed:m.currentSpeed, inVp:m.isInViewport}; });
|
||||
console.log('A', JSON.stringify(a)); console.log('C', JSON.stringify(c));
|
||||
console.log('FRAME GROWS:', c.frame>a.frame, ' (', a.frame.toFixed(1), '->', c.frame.toFixed(1), ')');
|
||||
await b.close();
|
||||
@@ -0,0 +1,32 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
await p.evaluate(()=>document.querySelector('[data-shader-demo]').scrollIntoView({block:'center'}));
|
||||
await new Promise(r=>setTimeout(r,300));
|
||||
// достанем mount из WeakMap нельзя, но проверим через глобальный хук: переопределим requestAnimationFrame до загрузки? уже поздно.
|
||||
// Вместо этого — вручную создадим ShaderMount и проверим frame рост + readPixels внутри rAF
|
||||
const res = await p.evaluate(async()=>{
|
||||
const mod = await import('/vendor/paper-shaders/index.js');
|
||||
const wrap = document.querySelector('[data-shader-demo] .card-shader');
|
||||
const cv = wrap.querySelector('canvas');
|
||||
// создадим свой mount того же шейдера в НОВЫЙ контейнер чтобы не конфликтовать
|
||||
const host = document.createElement('div'); host.style.cssText='position:fixed;left:0;top:0;width:200px;height:120px;z-index:9999';
|
||||
document.body.appendChild(host);
|
||||
const m = new mod.ShaderMount(host, mod.meshGradientFragmentShader, { u_colors:['#7c5cff','#00c2c7','#ff5c8a'], u_colorsCount:3, u_distortion:0.6, u_swirl:0.4, u_grainMixer:0.08, u_grainOverlay:0.04 }, {preserveDrawingBuffer:true}, 0.2);
|
||||
await new Promise(r=>setTimeout(r,500));
|
||||
const frame1 = m.getCurrentFrame();
|
||||
await new Promise(r=>setTimeout(r,500));
|
||||
const frame2 = m.getCurrentFrame();
|
||||
// читаем пиксель через свой canvas с preserveDrawingBuffer
|
||||
const c2 = host.querySelector('canvas');
|
||||
const gl = c2.getContext('webgl', {preserveDrawingBuffer:true}) || c2.getContext('webgl2',{preserveDrawingBuffer:true});
|
||||
let px='n/a';
|
||||
if(gl){ const a=new Uint8Array(4); gl.readPixels(10,10,1,1,gl.RGBA,gl.UNSIGNED_BYTE,a); px=Array.from(a); }
|
||||
m.dispose(); host.remove();
|
||||
return { frame1, frame2, animated: frame2>frame1, px };
|
||||
});
|
||||
console.log(JSON.stringify(res,null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,27 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,800));
|
||||
const r = await p.evaluate(async ()=>{
|
||||
const mod = await import('/vendor/paper-shaders/index.js');
|
||||
const { ShaderMount, meshGradientFragmentShader, getShaderColorFromString } = mod;
|
||||
const host = document.createElement('div'); host.style.cssText='width:300px;height:200px;position:relative';
|
||||
document.body.appendChild(host);
|
||||
const colors = ['#7c5cff','#00c2c7','#ff5c8a','#ffb347'].map(getShaderColorFromString);
|
||||
const uniforms = { u_colors: colors, u_colorsCount: colors.length, u_distortion:1.2, u_swirl:0.8, u_grainMixer:0.08, u_grainOverlay:0.04 };
|
||||
const m = new ShaderMount(host, meshGradientFragmentShader, uniforms, { preserveDrawingBuffer:true, antialias:true }, 1.0);
|
||||
const gl=m.gl, pr=m.program;
|
||||
const f=(n)=>{const l=gl.getUniformLocation(pr,n);const v=new Float32Array(4);gl.getUniform(pr,l,v);return Array.from(v).map(x=>+x.toFixed(3));};
|
||||
const fi=(n)=>{const l=gl.getUniformLocation(pr,n);const v=new Float32Array(1);gl.getUniform(pr,l,v);return v[0];};
|
||||
return {
|
||||
u_swirl: fi('u_swirl'),
|
||||
u_distortion: fi('u_distortion'),
|
||||
u_colorsCount: fi('u_colorsCount'),
|
||||
u_color0: f('u_colors[0]'),
|
||||
u_color1: f('u_colors[1]'),
|
||||
};
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,22 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const r = await p.evaluate(()=>{
|
||||
const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount;
|
||||
const gl=m.gl;
|
||||
const out=[];
|
||||
for(let i=0;i<4;i++){
|
||||
const loc=gl.getUniformLocation(m.program,'u_colors['+i+']');
|
||||
const v=new Float32Array(4);
|
||||
gl.getUniform(m.program,loc,v);
|
||||
out.push(Array.from(v).map(x=>+x.toFixed(3)));
|
||||
}
|
||||
const cnt=gl.getUniformLocation(m.program,'u_colorsCount');
|
||||
const cv=new Int32Array(1); gl.getUniform(m.program,cnt,cv);
|
||||
return { uColors: out, count: cv[0] };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,16 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1000));
|
||||
// принудительно рендерим два кадра с разным временем и берём toDataURL
|
||||
const r = await p.evaluate(()=>{
|
||||
const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount;
|
||||
const cv=m.canvasElement;
|
||||
m.render(0); const a=cv.toDataURL('image/png');
|
||||
m.render(8000); const c=cv.toDataURL('image/png');
|
||||
return { lenA:a.length, lenC:c.length, same: a===c, headA:a.slice(0,40) };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,18 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
const errs=[]; p.on('pageerror',e=>errs.push(e.message)); p.on('console',m=>{if(m.type()==='error')errs.push(m.text());});
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1500));
|
||||
const r = await p.evaluate(()=>{
|
||||
const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount;
|
||||
const gl=m.gl;
|
||||
m.render(performance.now()); m.render(performance.now());
|
||||
const W=m.canvasElement.width,H=m.canvasElement.height; const buf=new Uint8Array(W*H*4); gl.readPixels(0,0,W,H,gl.RGBA,gl.UNSIGNED_BYTE,buf);
|
||||
let bright=0,maxc=0; for(let i=0;i<buf.length;i+=4){const mx=Math.max(buf[i],buf[i+1],buf[i+2]); if(mx>120)bright++; maxc=Math.max(maxc,mx);}
|
||||
return { brightPixels: bright, maxChannel: maxc };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
console.log('ERRS', errs.slice(0,5));
|
||||
await b.close();
|
||||
@@ -0,0 +1,19 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const r = await p.evaluate(()=>{
|
||||
const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount;
|
||||
const gl=m.gl, pr=m.program;
|
||||
const gf=(n)=>gl.getUniform(pr, gl.getUniformLocation(pr,n));
|
||||
return {
|
||||
u_resolution: gf('u_resolution'),
|
||||
u_pixelRatio: gf('u_pixelRatio'),
|
||||
linkStatus: gl.getProgramParameter(pr, gl.LINK_STATUS),
|
||||
vsLog: gl.getShaderInfoLog(gl.getShader(gl.VERTEX_SHADER)),
|
||||
};
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,14 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const r = await p.evaluate(()=>{
|
||||
const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount;
|
||||
const gl=m.gl, pr=m.program;
|
||||
const gf=(n)=>gl.getUniform(pr, gl.getUniformLocation(pr,n));
|
||||
return { u_resolution: gf('u_resolution'), u_pixelRatio: gf('u_pixelRatio'), canvasW: m.canvasElement.width, canvasH: m.canvasElement.height };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
const errs=[]; p.on('pageerror',e=>errs.push('PE '+e.message));
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1000));
|
||||
// берём toDataURL двух кадров с интервалом — мой rAF должен сдвинуть currentFrame
|
||||
const a = await p.evaluate(()=>{ const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount; return m.canvasElement.toDataURL('image/png').length; });
|
||||
await new Promise(r=>setTimeout(r,1500));
|
||||
const c = await p.evaluate(()=>{ const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount; return m.canvasElement.toDataURL('image/png').length; });
|
||||
console.log('dataURL length t1:', a, ' t2:', c, ' CHANGED:', a!==c);
|
||||
console.log('errs', errs.slice(0,3));
|
||||
await b.close();
|
||||
@@ -0,0 +1,15 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1000));
|
||||
const r = await p.evaluate(()=>{
|
||||
const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount;
|
||||
const cv=m.canvasElement;
|
||||
m.setFrame(0); const a=cv.toDataURL('image/png');
|
||||
m.setFrame(10000); const c=cv.toDataURL('image/png');
|
||||
return { same: a===c, lenA:a.length, lenC:c.length };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,17 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const r = await p.evaluate(()=>{
|
||||
const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount;
|
||||
const gl=m.gl;
|
||||
m.setUniforms({ u_colorsCount: 4, u_colors: [[0.486,0.361,1,1],[0,0.761,0.78,1],[1,0.361,0.541,1],[1,0.702,0.278,1]] });
|
||||
gl.drawArrays(gl.TRIANGLES,0,6);
|
||||
const px=new Uint8Array(4); gl.readPixels(360,220,1,1,gl.RGBA,gl.UNSIGNED_BYTE,px);
|
||||
const cnt=gl.getUniformLocation(m.program,'u_colorsCount'); const cv=new Int32Array(1); gl.getUniform(m.program,cnt,cv);
|
||||
return { center:Array.from(px), count: cv[0] };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,21 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,800));
|
||||
const r = await p.evaluate(async ()=>{
|
||||
const mod = await import('/vendor/paper-shaders/index.js');
|
||||
const { ShaderMount, meshGradientFragmentShader, getShaderColorFromString } = mod;
|
||||
const host = document.createElement('div'); host.style.cssText='width:300px;height:200px;position:relative';
|
||||
document.body.appendChild(host);
|
||||
const colors = ['#7c5cff','#00c2c7','#ff5c8a','#ffb347'].map(getShaderColorFromString);
|
||||
const m = new ShaderMount(host, meshGradientFragmentShader, {}, { preserveDrawingBuffer:true, antialias:true }, 1.0);
|
||||
m.setUniforms({ u_colors: colors, u_colorsCount: colors.length, u_distortion:1.2, u_swirl:0.8 });
|
||||
const gl=m.gl, pr=m.program;
|
||||
const fi=(n)=>{const l=gl.getUniformLocation(pr,n);const v=new Float32Array(1);gl.getUniform(pr,l,v);return v[0];};
|
||||
const f=(n)=>{const l=gl.getUniformLocation(pr,n);const v=new Float32Array(4);gl.getUniform(pr,l,v);return Array.from(v).map(x=>+x.toFixed(3));};
|
||||
return { u_swirl: fi('u_swirl'), u_colorsCount: fi('u_colorsCount'), u_color0: f('u_colors[0]') };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1400});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
await p.evaluate(()=>document.querySelector('#sec-shader-grid')?.scrollIntoView());
|
||||
await new Promise(r=>setTimeout(r,800));
|
||||
const r = await p.evaluate(()=>{
|
||||
const shaderCard=document.querySelector('#sec-shader-grid .neu-card--shader');
|
||||
const plainCard=document.querySelector('#sec-shader-grid .neu-card:not(.neu-card--shader)');
|
||||
const cs=getComputedStyle(shaderCard);
|
||||
const after=getComputedStyle(shaderCard,'::after');
|
||||
const plain=getComputedStyle(plainCard);
|
||||
const countShadows=(s)=>s.split(/,(?![^()]*\))/).filter(x=>x.trim()).length;
|
||||
return {
|
||||
shaderBoxShadow: cs.boxShadow.slice(0,80)+'...', shaderShadowCount: countShadows(cs.boxShadow),
|
||||
afterBoxShadow: after.boxShadow.slice(0,80)+'...', afterShadowCount: countShadows(after.boxShadow),
|
||||
afterZ: after.zIndex, beforeZ: getComputedStyle(shaderCard,'::before').zIndex,
|
||||
plainShadowCount: countShadows(plain.boxShadow),
|
||||
};
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,24 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
const errs=[]; p.on('console',m=>{if(m.type()==='error')errs.push(m.text())}); p.on('pageerror',e=>errs.push('PE '+e.message));
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1500));
|
||||
const info = await p.evaluate(()=>{
|
||||
const hosts=[...document.querySelectorAll('#sec-shader .card-shader-host')];
|
||||
return hosts.map(h=>{
|
||||
const cv=h.querySelector('canvas');
|
||||
return { sel:h.dataset.shader, hasCanvas:!!cv, w:cv?.width, h:cv?.height, mounted:h.dataset.mounted };
|
||||
});
|
||||
});
|
||||
// снимем пиксель чтобы убедиться что шейдер реально рисует (не пустой canvas)
|
||||
const pix = await p.evaluate(()=>{
|
||||
const cv=document.querySelector('#sec-shader .card-shader-host canvas');
|
||||
if(!cv) return 'no-canvas';
|
||||
const gl=cv.getContext('webgl2')||cv.getContext('webgl');
|
||||
if(!gl) return 'no-gl';
|
||||
const px=new Uint8Array(4); gl.readPixels(Math.floor(cv.width/2),Math.floor(cv.height/2),1,1,gl.RGBA,gl.UNSIGNED_BYTE,px);
|
||||
return Array.from(px).join(',');
|
||||
});
|
||||
console.log(JSON.stringify({info, centerPixel:pix, errs}, null, 1));
|
||||
await b.close();
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1280,height:1000});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
// подпишемся на клик по ссылке внутри страницы
|
||||
await p.evaluate(()=>{
|
||||
window.__clicked=false;
|
||||
document.querySelector('#sec-shader a.contact-card').addEventListener('click', ()=>{ window.__clicked=true; }, true);
|
||||
});
|
||||
const link = await p.$('#sec-shader a.contact-card');
|
||||
const box = await link.boundingBox();
|
||||
await p.mouse.click(box.x+box.width/2, box.y+box.height/2);
|
||||
await new Promise(r=>setTimeout(r,300));
|
||||
const clicked = await p.evaluate(()=>window.__clicked);
|
||||
// hover тоже
|
||||
await p.mouse.move(box.x+box.width/2, box.y+box.height/2);
|
||||
await new Promise(r=>setTimeout(r,400));
|
||||
const hover = await p.evaluate(()=>getComputedStyle(document.querySelector('#sec-shader a.contact-card')).transform);
|
||||
console.log(JSON.stringify({clicked, hover},null,1));
|
||||
await b.close();
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1280,height:1000});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const r = await p.evaluate(()=>{
|
||||
const card=document.querySelector('#sec-shader a.contact-card');
|
||||
const rect=card.getBoundingClientRect();
|
||||
const x=rect.x+rect.width/2, y=rect.y+rect.height/2;
|
||||
const el=document.elementFromPoint(x,y);
|
||||
const path=[];
|
||||
let e=el; while(e && path.length<5){ path.push(e.className||e.tagName); e=e.parentElement; }
|
||||
// что у canvas
|
||||
const cv=card.querySelector('canvas');
|
||||
return {
|
||||
topEl: el.className||el.tagName,
|
||||
path,
|
||||
canvasPE: cv?getComputedStyle(cv).pointerEvents:'', canvasZ: cv?getComputedStyle(cv).zIndex:'',
|
||||
cardZ: getComputedStyle(card).zIndex, cardPos: getComputedStyle(card).position,
|
||||
};
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1280,height:1000});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1000));
|
||||
await p.evaluate(()=>document.querySelector('#sec-shader').scrollIntoView());
|
||||
await new Promise(r=>setTimeout(r,400));
|
||||
await p.evaluate(()=>{
|
||||
window.__clicked=false;
|
||||
const c=document.querySelector('#sec-shader a.contact-card');
|
||||
c.addEventListener('click', ()=>{ window.__clicked=true; }, true);
|
||||
});
|
||||
const box = await p.$eval('#sec-shader a.contact-card', el=>{const r=el.getBoundingClientRect();return {x:r.x,y:r.y,w:r.width,h:r.height};});
|
||||
const x=box.x+box.w/2, y=box.y+box.h/2;
|
||||
await p.mouse.move(x,y);
|
||||
await new Promise(r=>setTimeout(r,400));
|
||||
const hover = await p.evaluate(()=>getComputedStyle(document.querySelector('#sec-shader a.contact-card')).transform);
|
||||
await p.mouse.click(x,y);
|
||||
await new Promise(r=>setTimeout(r,300));
|
||||
const clicked = await p.evaluate(()=>window.__clicked);
|
||||
const top = await p.evaluate((x,y)=>{const e=document.elementFromPoint(x,y);return e?(e.className||e.tagName):'null';}, x, y);
|
||||
console.log(JSON.stringify({hover, clicked, topElAtCenter: top},null,1));
|
||||
await b.close();
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1280,height:1000});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1000));
|
||||
const meta = await p.evaluate(()=>{
|
||||
const c=document.querySelector('#sec-shader a.contact-card');
|
||||
const r=c.getBoundingClientRect();
|
||||
return { docH: document.body.scrollHeight, viewH: window.innerHeight,
|
||||
cardTop: r.top, cardBottom: r.bottom, cardRect: {x:r.x,y:r.y,w:r.width,h:r.height} };
|
||||
});
|
||||
console.log('before scroll', JSON.stringify(meta));
|
||||
await p.evaluate(()=>document.querySelector('#sec-shader a.contact-card').scrollIntoView({block:'center'}));
|
||||
await new Promise(r=>setTimeout(r,500));
|
||||
const after = await p.evaluate(()=>{
|
||||
const c=document.querySelector('#sec-shader a.contact-card');
|
||||
const r=c.getBoundingClientRect();
|
||||
const cx=r.x+r.width/2, cy=r.y+r.height/2;
|
||||
const e=document.elementFromPoint(cx,cy);
|
||||
return { cardTop: r.top, cardBottom: r.bottom, topEl: e?(e.className||e.tagName):'null', cx, cy };
|
||||
});
|
||||
console.log('after scroll', JSON.stringify(after));
|
||||
await b.close();
|
||||
@@ -0,0 +1,16 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader'] });
|
||||
const p = await b.newPage();
|
||||
const errs=[]; p.on('console',m=>{if(m.type()==='error')errs.push(m.text())}); p.on('pageerror',e=>errs.push('PE '+e.message));
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const r = await p.evaluate(()=>{
|
||||
const card=document.querySelector('#sec-shader .card-shader-host .contact-card');
|
||||
const cs=getComputedStyle(card);
|
||||
const wrap=document.querySelector('#sec-shader .card-shader');
|
||||
return { boxShadow: cs.boxShadow.slice(0,40), glow: cs.backgroundImage.slice(0,30),
|
||||
shaderLayer: getComputedStyle(wrap).position, shaderZ: getComputedStyle(wrap).zIndex,
|
||||
contentZ: getComputedStyle(card.querySelector('.contact-card__body')).zIndex };
|
||||
});
|
||||
console.log(JSON.stringify({r, errs},null,1));
|
||||
await b.close();
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1280,height:1000});
|
||||
const errs=[]; p.on('console',m=>{if(m.type()==='error')errs.push(m.text())}); p.on('pageerror',e=>errs.push('PE '+e.message));
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1000));
|
||||
const link = await p.$('#sec-shader a.contact-card');
|
||||
await link.hover();
|
||||
await new Promise(r=>setTimeout(r,400));
|
||||
const hover = await p.evaluate(()=>getComputedStyle(document.querySelector('#sec-shader a.contact-card')).transform);
|
||||
let popup='none';
|
||||
p.once('popup', ()=>{ popup='popup'; });
|
||||
await link.click({delay:50});
|
||||
await new Promise(r=>setTimeout(r,300));
|
||||
const geo = await p.evaluate(()=>{
|
||||
const li=document.querySelector('#sec-shader li'); const card=li.querySelector('.contact-card');
|
||||
const cv=card.querySelector('canvas');
|
||||
return { liH:Math.round(li.getBoundingClientRect().height), cardH:Math.round(card.getBoundingClientRect().height),
|
||||
canvasInCard: card.contains(cv), canvasPE: cv?getComputedStyle(cv).pointerEvents:'none' };
|
||||
});
|
||||
console.log(JSON.stringify({hover, popup, geo, errs},null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,26 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1280,height:1000});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const info = await p.evaluate(()=>{
|
||||
const host=document.querySelector('#sec-shader .card-shader-host');
|
||||
const li=host; const card=host.querySelector('.contact-card'); const canvas=host.querySelector('canvas');
|
||||
const lr=getComputedStyle(li), cr=getComputedStyle(card), cvr=getComputedStyle(canvas);
|
||||
return {
|
||||
liDisplay: lr.display, liPosition: lr.position, liW: li.getBoundingClientRect().width,
|
||||
cardW: card.getBoundingClientRect().width, cardH: card.getBoundingClientRect().height,
|
||||
canvasPointer: cvr.pointerEvents, canvasZ: cvr.zIndex, canvasInset: cvr.position,
|
||||
cardPointer: cr.pointerEvents,
|
||||
};
|
||||
});
|
||||
console.log(JSON.stringify(info,null,1));
|
||||
// тест клика по ссылке
|
||||
const link = await p.$('#sec-shader a.contact-card');
|
||||
const box = await link.boundingBox();
|
||||
await p.mouse.click(box.x+box.width/2, box.y+box.height/2);
|
||||
await new Promise(r=>setTimeout(r,300));
|
||||
const url = p.url();
|
||||
console.log('after click url:', url, '(same page expected, external link opens new tab)');
|
||||
await b.close();
|
||||
@@ -0,0 +1,21 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
const logs=[];
|
||||
p.on('console', m=>logs.push('['+m.type()+'] '+m.text()));
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1000));
|
||||
const r = await p.evaluate(()=>{
|
||||
const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount;
|
||||
const gl=m.gl;
|
||||
// проверим компиляцию шейдеров напрямую
|
||||
const vs=gl.getParameter(gl.VERTEX_SHADER);
|
||||
// считаем context lost
|
||||
const lost = gl.isContextLost();
|
||||
// размер drawing buffer
|
||||
const dbw=gl.drawingBufferWidth, dbh=gl.drawingBufferHeight;
|
||||
return { contextLost: lost, dbW: dbw, dbH: dbh, glError: gl.getError() };
|
||||
});
|
||||
console.log('R', JSON.stringify(r));
|
||||
console.log('LOGS:\n'+logs.slice(0,15).join('\n'));
|
||||
await b.close();
|
||||
@@ -0,0 +1,12 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
import fs from 'fs';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1500,deviceScaleFactor:1});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1800));
|
||||
const el = await p.$('#sec-shader-grid');
|
||||
const box = await el.boundingBox();
|
||||
await el.screenshot({ path: '/tmp/matrix.png' });
|
||||
console.log('saved', box?.width, box?.height);
|
||||
await b.close();
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
const puppeteer = require('puppeteer');
|
||||
(async () => {
|
||||
const browser = await puppeteer.launch({ headless: 'new', args: ['--no-sandbox','--disable-setuid-sandbox'] });
|
||||
const page = await browser.newPage();
|
||||
await page.setViewport({ width: 1278, height: 900, deviceScaleFactor: 1 });
|
||||
await page.goto('http://localhost:4175/cases/ai-platform-primo-rpa/', { waitUntil: 'networkidle0' });
|
||||
await page.waitForSelector('[data-mini-projects-list]');
|
||||
const el = await page.$('[data-mini-projects-list]');
|
||||
await el.evaluate(e => e.scrollIntoView({block:'center'}));
|
||||
await new Promise(r => setTimeout(r, 600));
|
||||
await el.screenshot({ path: '/tmp/related_1278.png' });
|
||||
await browser.close();
|
||||
console.log('shot saved');
|
||||
})().catch(e => { console.error(e); process.exit(1); });
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
import crypto from 'crypto';
|
||||
import fs from 'fs';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1000));
|
||||
await p.evaluate(()=>document.querySelector('[data-shader-demo]').scrollIntoView({block:'center'}));
|
||||
await new Promise(r=>setTimeout(r,500));
|
||||
const h1 = await p.screenshot({encoding:'binary'}); await fs.promises.writeFile('/tmp/s1.png', h1);
|
||||
await new Promise(r=>setTimeout(r,1500));
|
||||
const h2 = await p.screenshot({encoding:'binary'}); await fs.promises.writeFile('/tmp/s2.png', h2);
|
||||
const m1=crypto.createHash('md5').update(h1).digest('hex'); const m2=crypto.createHash('md5').update(h2).digest('hex');
|
||||
console.log('bytes', h1.length, h2.length, 'md5equal', m1===m2);
|
||||
await b.close();
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1280,height:1000});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1000));
|
||||
await p.evaluate(()=>{ window.__clicked=false; const c=document.querySelector('#sec-shader a.contact-card'); c.addEventListener('click',()=>window.__clicked=true,true); });
|
||||
const link = await p.$('#sec-shader a.contact-card');
|
||||
await link.hover();
|
||||
await new Promise(r=>setTimeout(r,400));
|
||||
const hover = await p.evaluate(()=>getComputedStyle(document.querySelector('#sec-shader a.contact-card')).transform);
|
||||
await link.click({delay:50});
|
||||
await new Promise(r=>setTimeout(r,300));
|
||||
const clicked = await p.evaluate(()=>window.__clicked);
|
||||
console.log(JSON.stringify({hover, clicked},null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,32 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1280,height:1000});
|
||||
const errs=[]; p.on('console',m=>{if(m.type()==='error')errs.push(m.text())}); p.on('pageerror',e=>errs.push('PE '+e.message));
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1500));
|
||||
const geo = await p.evaluate(()=>{
|
||||
const li=document.querySelector('#sec-shader li');
|
||||
const card=li.querySelector('.contact-card');
|
||||
const canvas=li.querySelector('canvas');
|
||||
return {
|
||||
liH: Math.round(li.getBoundingClientRect().height),
|
||||
cardH: Math.round(card.getBoundingClientRect().height),
|
||||
canvasInCard: canvas ? card.contains(canvas) : false,
|
||||
canvasPE: canvas ? getComputedStyle(canvas).pointerEvents : 'no-canvas',
|
||||
cardPE: getComputedStyle(card).pointerEvents,
|
||||
};
|
||||
});
|
||||
// hover + click test
|
||||
const link = await p.$('#sec-shader a.contact-card');
|
||||
const box = await link.boundingBox();
|
||||
await p.mouse.move(box.x+box.width/2, box.y+box.height/2);
|
||||
await new Promise(r=>setTimeout(r,200));
|
||||
const hoverTransform = await p.evaluate(()=>getComputedStyle(document.querySelector('#sec-shader a.contact-card')).transform);
|
||||
// click -> should open new tab (we block navigation, just check no error)
|
||||
const newTarget = await Promise.race([
|
||||
new Promise(res=>p.once('popup', t=>res('popup'))),
|
||||
new Promise(res=>setTimeout(()=>res('none'), 800))
|
||||
]);
|
||||
console.log(JSON.stringify({geo, hoverTransform, newTarget, errs}, null, 1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,17 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
import sharp from 'sharp';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1280,height:1400,deviceScaleFactor:1});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,2000));
|
||||
const el = await p.$('#sec-shader');
|
||||
await el.screenshot({ path: '/tmp/shader-sec.png' });
|
||||
// analyse average + stddev of color
|
||||
const {data,info} = await sharp('/tmp/shader-sec.png').raw().toBuffer({resolveWithObject:true});
|
||||
let n=info.width*info.height, rs=0,gs=0,bs=0; const cols=new Set();
|
||||
for(let i=0;i<data.length;i+=3){ rs+=data[i]; gs+=data[i+1]; bs+=data[i+2];
|
||||
if(i%900===0) cols.add(`${data[i]>>4},${data[i+1]>>4},${data[i+2]>>4}`); }
|
||||
console.log('avg rgb', Math.round(rs/n),Math.round(gs/n),Math.round(bs/n));
|
||||
console.log('distinct coarse colors sampled:', cols.size);
|
||||
await b.close();
|
||||
@@ -0,0 +1,19 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const r = await p.evaluate(()=>{
|
||||
const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount;
|
||||
const wrap=m.parentElement;
|
||||
return {
|
||||
canvasW:m.canvasElement.width, canvasH:m.canvasElement.height,
|
||||
canvasCSS: getComputedStyle(m.canvasElement).width+'x'+getComputedStyle(m.canvasElement).height,
|
||||
parentW:m.parentWidth, parentH:m.parentHeight,
|
||||
wrapRect: (()=>{const r=wrap.getBoundingClientRect();return {w:r.width,h:r.height};})(),
|
||||
hasRO: !!m.resizeObserver,
|
||||
};
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
@@ -11,7 +11,7 @@
|
||||
{{> head-links}}
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<body class="home">
|
||||
{{> header-home}}
|
||||
{{> fab-stack}}
|
||||
<main id="main">
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
# Card Columns — плагин-вид для Obsidian Bases
|
||||
|
||||
- **Источник:** `public/cases/card-columns-obsidian/index.html`
|
||||
- **eyebrow:** Obsidian Bases · Plugin
|
||||
- **meta description:** Кейс: Card Columns, плагин-вид для Obsidian Bases. Показывает заметки как карточки, разложенные по колонкам, с фильтрацией тегов по И/ИЛИ.
|
||||
|
||||
---
|
||||
|
||||
**Заметка по путям к медиа:** файлы кладутся в `public/assets/card-columns-obsidian/`, в разметке страницы пути `../assets/card-columns-obsidian/файл.webp`. Форматы: WebP (изображения, постеры), WebM + MP4 (видео).
|
||||
|
||||
## Brief (блок метаданных на странице)
|
||||
|
||||
- **Роль:** Продуктовый дизайн и разработка
|
||||
- **Платформа:** Obsidian Bases
|
||||
- **Статус:** Рабочий плагин, open source (MIT)
|
||||
- **Команда:** Соло, пет-проект
|
||||
|
||||
## Введение
|
||||
|
||||
В Obsidian появились Bases, отдельный тип файла, который показывает заметки не текстом, а в разных видах: таблицей, карточками, деревом. Стандартный вид карточек мне не зашёл: он плоский, без группировки, и в нём не разобраться, когда заметок сотни. Я хотел видеть их раскладку по колонкам, как канбан, но без лишнего веса. Так появился плагин-вид Card Columns.
|
||||
|
||||
## Контекст
|
||||
|
||||
Bases, это не заметка и не отдельная база данных. Это запрос к vault-у: выбираешь заметки по фильтру, и фреймворк рисует их в выбранном виде. У самого Obsidian есть встроенный вид карточек, но он одноплановый: нет группировки по свойствам, нет нормальной фильтрации. Я решил сделать свой вид, который встраивается в переключатель Bases наравне со штатными.
|
||||
|
||||
Главное ограничение было в самом фреймворке: плагин не хранит данные, а рисует то, что выдал Bases-запрос (Sort, Filter, Properties, Search из тулбара). Значит, вся логика выборки остаётся на Bases, а моя задача, только представление и навигация по нему.
|
||||
|
||||
## Задача
|
||||
|
||||
Спроектировать и собрать view-плагин для Obsidian Bases: заметки из запроса показываются карточками, разложенными по колонкам, а по колонкам легко ориентироваться и отбирать нужное. Вид должен жить в переключателе Bases рядом со штатными и не ломать встроенный тулбар (сортировку, фильтр, поиск).
|
||||
|
||||
> **Callout (📌):** Главный риск, сделать вид, который конфликтует со штатным тулбаром Bases. Тогда пользователь теряет сортировку и поиск, ради которых Bases и берут. Этого нельзя было допустить.
|
||||
|
||||
## Решение
|
||||
|
||||
Плагин добавляет в Bases вид «Columns». Карточки строятся из результатов Bases-запроса, группировка задаётся свойством, а отбор, кликабельными тегами.
|
||||
|
||||
### Группировка по любому свойству
|
||||
|
||||
Колонки формируются из Group by в тулбаре Bases, по тегу, статусу, категории или любому frontmatter-свойству. Меняешь свойство в запросе, и доска пересобирается сама. Так одна и та же база закрывает разные разрезы: проекты по статусу, заметки по тегам, задачи по приоритету.
|
||||
|
||||
### Фильтр тегов по И и ИЛИ
|
||||
|
||||
Это то, ради чего плагин и задумывался. Под тулбаром, пилюли тегов, по клику они отсеивают карточки по всем колонкам сразу:
|
||||
|
||||
- Левый клик по тегу, показать только его (сбрасывает остальные фильтры).
|
||||
- Левый клик по следующему тегу, показать заметки с ЛЮБЫМ из выбранных (режим ИЛИ).
|
||||
- Ctrl+Клик или правый клик, переключить тег, не сбрасывая выбор.
|
||||
- Кнопка OR/AND, переключить между «любой из» и «все перечисленные» для нескольких тегов.
|
||||
- All, снять все фильтры.
|
||||
|
||||
Связка «ИЛИ-добавление левым кликом + точный toggle через Ctrl» получилась интуитивной: быстрый отбор не сбивает то, что уже выбрано. Альтернативу, вынести фильтр в модалку, отверг сразу: лишний клик и потеря контекста того, что уже отфильтровано.
|
||||
|
||||
### Карточки и обложки
|
||||
|
||||
По каждой заметке рисуются свойства как чипы, текст, теги, ссылки, булевы, даты. Можно показать обложку: из первой картинки в заметке или из отдельного свойства. У обложки полный контроль, соотношение сторон (Auto, 1:1, 3:2, 4:3, 16:9), рамка, вписывание (cover/contain), ориентация и место на карточке (над заголовком, под ним, после всего).
|
||||
|
||||
### Что заведено в настройки
|
||||
|
||||
Всю внешнюю вариативность я вынел в gear-меню, разбив на четыре секции, чтобы вид подстраивался под разные базы, а не под мой единственный сценарий.
|
||||
|
||||
**General**
|
||||
|
||||
- Куда открывать карточку: активная панель, всплывающее окно, новая вкладка, сплит вправо / вниз.
|
||||
- Ширина карточки (px).
|
||||
- Колонок в группе (1–6), сетка внутри колонки.
|
||||
- Зебра колонок (чередование фона для сканирования).
|
||||
- Masonry-раскладка (карточки заполняют вертикальные пустоты).
|
||||
|
||||
**Title**
|
||||
|
||||
- Перенос заголовка, жирный заголовок, размер шрифта (px).
|
||||
|
||||
**Properties**
|
||||
|
||||
- Раскладка чипов: стек (вертикально) или сетка (компактно в строку).
|
||||
- Перенос многострочных значений, размер шрифта.
|
||||
- Формат даты и даты-времени + локаль (Moment.js).
|
||||
|
||||
**Cover**
|
||||
|
||||
- Источник: нет / первая картинка в заметке / свойство-обложка.
|
||||
- Стиль (без рамки / с рамкой), соотношение сторон, ориентация, вписывание, позиция на карточке.
|
||||
|
||||
> **Callout (💡):** Сплит-превью сделал как в самом Obsidian: левый клик переиспользует панель, Ctrl+Клик, новую вкладку внутри сплита. Без этого на широком экране карточки неудобно просматривать рядом с доской.
|
||||
|
||||
### Работает внутри штатного тулбара
|
||||
|
||||
Вид цепляется к BasesView-фреймворку, поэтому сортировка, фильтр, свойства и поиск из тулбара Bases остаются рабочими. Плагин только рисует результат запроса, данные не дублируются и не зависят от отдельного хранилища.
|
||||
|
||||
## Результат
|
||||
|
||||
Вид закрыл мою боль: Bases-запрос теперь читается как доска, а не как плоская лента карточек. Группировка по свойству + отбор по тегам И/ИЛИ, то, чего не хватало штатному виду. Всё крутится на запросе Bases, так что перенос vault-а и синхронизация ничего не ломают.
|
||||
|
||||
Метрики у пет-проекта нет, и придумывать её не стану. Проверяю проще: юзабилити на себе в ежедневной работе. Критерий, сколько действий нужно, чтобы отобрать заметки по двум тегам и найти нужную карточку. В штатном виде карточек это был скролл ленты с ручным поиском по заголовкам; здесь, два клика по пилюлям и колонка перед глазами. Если бы замерял всерьёз, считал бы время на задачу на выборке из 20–30 заметок до и после, но на своей повседневной базе разница заметна и без секундомера.
|
||||
|
||||
Что сделал бы иначе. Drag-and-drop карточек между колонками не стал делать сознательно, это меняет свойство в заметке, и для view-плагина это отдельный риск целостности данных. Но вижу запрос на это у пользователей, и, возможно, добавлю как опциональный режим. А пока плагин живёт вручную (через community-каталог ещё не прошёл), это единственное, что мешает им пользоваться сходу.
|
||||
|
||||
> **Callout (✅):** Главный вывод: вид для Bases получается рабочим только тогда, когда он уважает тулбар фреймворка. Я добавил представление, а не вторую систему хранения, и заметки остались обычными заметками.
|
||||
|
||||
## Медиа-плейсхолдеры (в HTML закомментированы)
|
||||
|
||||
| Слот | Файл | Что показывать |
|
||||
|---|---|---|
|
||||
| Обзор | `overview.webp` | Вид Card Columns поверх `.base` файла |
|
||||
| Колонки | `board.webp` | Колонки карточек с группировкой по свойству |
|
||||
| Фильтр | `filter.webm` / `filter.mp4` + `filter-poster.webp` | Фильтрация по тегам, OR и AND |
|
||||
| Настройки | `settings.webp` | Gear-меню с секциями |
|
||||
|
||||
Ещё один слот (`note-before.webp`) остался в шаблоне из ранней версии и сейчас не используется, удалить при вставке медиа.
|
||||
|
||||
## Источники фактуры
|
||||
|
||||
- Репозиторий: `https://github.com/mamadaevv/card-columns` (лицензия MIT).
|
||||
- Все параметры кастомизации и логика фильтрации взяты из README репозитория.
|
||||
- Drag-and-drop в плагине **отсутствует**: он есть у соседнего `ewerx/obsidian-bases-kanban`, не путать.
|
||||
@@ -0,0 +1,14 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const top = await p.evaluate(()=>{ const r=document.querySelector('[data-shader-demo]').getBoundingClientRect(); return r.top+window.scrollY; });
|
||||
await p.evaluate((t)=>window.scrollTo(0, t-150), top);
|
||||
await new Promise(r=>setTimeout(r,700));
|
||||
await p.screenshot({path:'/tmp/t1.png'});
|
||||
await new Promise(r=>setTimeout(r,2500));
|
||||
await p.screenshot({path:'/tmp/t2.png'});
|
||||
console.log('done');
|
||||
await b.close();
|
||||
@@ -0,0 +1,21 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,800));
|
||||
const r = await p.evaluate(()=>{
|
||||
const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount;
|
||||
const gl=m.gl;
|
||||
// два render подряд, потому что drawArrays инициализируется лениво на 1-м вызове
|
||||
m.render(performance.now()); m.render(performance.now());
|
||||
const px=new Uint8Array(4); gl.readPixels(Math.floor(m.canvasElement.width/2), Math.floor(m.canvasElement.height/2),1,1,gl.RGBA,gl.UNSIGNED_BYTE,px);
|
||||
// и с разным временем
|
||||
m.setFrame(0); m.render(performance.now()); m.render(performance.now());
|
||||
const px0=new Uint8Array(4); gl.readPixels(50,50,1,1,gl.RGBA,gl.UNSIGNED_BYTE,px0);
|
||||
m.setFrame(10000); m.render(performance.now()); m.render(performance.now());
|
||||
const px1=new Uint8Array(4); gl.readPixels(50,50,1,1,gl.RGBA,gl.UNSIGNED_BYTE,px1);
|
||||
return { centerAfter2: Array.from(px), at0: Array.from(px0), at10000: Array.from(px1) };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,20 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const r = await p.evaluate(()=>{
|
||||
const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount;
|
||||
const gl=m.gl;
|
||||
const out=[];
|
||||
for(let i=0;i<4;i++){
|
||||
const loc=gl.getUniformLocation(m.program,'u_colors['+i+']');
|
||||
const v=new Float32Array(4);
|
||||
gl.getUniform(gl,m.program,loc,v); // WebGL2? попробуем
|
||||
out.push(Array.from(v));
|
||||
}
|
||||
return { uColors: out, colorsCount: (()=>{const l=gl.getUniformLocation(m.program,'u_colorsCount');const v=new Int32Array(1);try{gl.getUniform(gl,m.program,l,v);}catch(e){return 'err';}return v[0];})() };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,22 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1000));
|
||||
const r = await p.evaluate(()=>{
|
||||
const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount;
|
||||
const gl=m.gl;
|
||||
// u_time location
|
||||
const tloc = gl.getUniformLocation(m.program, 'u_time');
|
||||
// прочитаем текущее значение u_time (если location валиден)
|
||||
let tval=null;
|
||||
try { const buf=new Float32Array(1); gl.getUniform(gl, m.program, tloc); } catch(e){}
|
||||
// применим setFrame и проверим, что вообще рисуется (readPixels центр)
|
||||
m.setFrame(500);
|
||||
const px=new Uint8Array(4);
|
||||
gl.readPixels(Math.floor(m.canvasElement.width/2), Math.floor(m.canvasElement.height/2), 1,1, gl.RGBA, gl.UNSIGNED_BYTE, px);
|
||||
return { hasProgram: !!m.program, uTimeLocIsNull: tloc===null, centerPx: Array.from(px) };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,19 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const r = await p.evaluate(()=>{
|
||||
const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount;
|
||||
const gl=m.gl;
|
||||
const uloc=gl.getUniformLocation(m.program,'u_time');
|
||||
const read=(x,y)=>{const px=new Uint8Array(4);gl.readPixels(x,y,1,1,gl.RGBA,gl.UNSIGNED_BYTE,px);return Array.from(px);};
|
||||
const draw=()=>{gl.useProgram(m.program);gl.drawArrays(gl.TRIANGLES,0,6);};
|
||||
gl.uniform1f(uloc,0); draw(); const a=read(360,220);
|
||||
gl.uniform1f(uloc,50); draw(); const c=read(360,220);
|
||||
gl.uniform1f(uloc,200); draw(); const d=read(360,220);
|
||||
return { t0:a, t50:c, t200:d };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const r = await p.evaluate(()=>{
|
||||
const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount;
|
||||
const gl=m.gl;
|
||||
gl.getError();
|
||||
m.render(performance.now()); m.render(performance.now()); // прогрев drawArrays
|
||||
const px=new Uint8Array(4); gl.readPixels(360,220,1,1,gl.RGBA,gl.UNSIGNED_BYTE,px);
|
||||
const a=m.canvasElement.toDataURL('image/png');
|
||||
m.setFrame(0); m.render(performance.now()); m.render(performance.now());
|
||||
const p0=new Uint8Array(4); gl.readPixels(40,40,1,1,gl.RGBA,gl.UNSIGNED_BYTE,p0);
|
||||
const u0=m.canvasElement.toDataURL('image/png');
|
||||
m.setFrame(10000); m.render(performance.now()); m.render(performance.now());
|
||||
const p1=new Uint8Array(4); gl.readPixels(40,40,1,1,gl.RGBA,gl.UNSIGNED_BYTE,p1);
|
||||
const u1=m.canvasElement.toDataURL('image/png');
|
||||
return { centerOpaque: Array.from(px), at0: Array.from(p0), at10000: Array.from(p1), dataURLchanged: u0!==u1 };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,21 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
await p.setViewport({width:1100,height:1300});
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1200));
|
||||
const r = await p.evaluate(()=>{
|
||||
const m=document.querySelector('[data-shader-demo] .card-shader').paperShaderMount;
|
||||
const gl=m.gl;
|
||||
const before={ w:m.canvasElement.width, h:m.canvasElement.height, vp:[gl.getParameter(gl.VIEWPORT)[0],gl.getParameter(gl.VIEWPORT)[1],gl.getParameter(gl.VIEWPORT)[2],gl.getParameter(gl.VIEWPORT)[3]] };
|
||||
// принудительно resize + render
|
||||
m.handleResize?.();
|
||||
m.render(performance.now()); m.render(performance.now());
|
||||
const px=new Uint8Array(4); gl.readPixels(360,220,1,1,gl.RGBA,gl.UNSIGNED_BYTE,px);
|
||||
// макс по canvas
|
||||
const W=m.canvasElement.width,H=m.canvasElement.height; const buf=new Uint8Array(W*H*4); gl.readPixels(0,0,W,H,gl.RGBA,gl.UNSIGNED_BYTE,buf);
|
||||
let maxc=0; for(let i=0;i<buf.length;i+=4) maxc=Math.max(maxc,buf[i],buf[i+1],buf[i+2]);
|
||||
return { before, centerAfter:Array.from(px), maxChannel:maxc };
|
||||
});
|
||||
console.log(JSON.stringify(r,null,1));
|
||||
await b.close();
|
||||
@@ -0,0 +1,28 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
const b = await puppeteer.launch({ args:['--no-sandbox','--disable-setuid-sandbox','--use-gl=angle','--enable-unsafe-swiftshader','--ignore-gpu-blocklist'] });
|
||||
const p = await b.newPage();
|
||||
const errs=[]; p.on('console',m=>{ if(['error','warning'].includes(m.type())) errs.push(m.type()+': '+m.text()); });
|
||||
p.on('pageerror',e=>errs.push('PAGEERR: '+e.message));
|
||||
await p.goto('http://10.200.201.3:4175/_lab/neu-card.html',{waitUntil:'load',timeout:60000});
|
||||
await new Promise(r=>setTimeout(r,1500));
|
||||
const r = await p.evaluate(()=>{
|
||||
const wrap=document.querySelector('[data-shader-demo] .card-shader');
|
||||
const card=document.querySelector('[data-shader-demo]');
|
||||
const cv=wrap?wrap.querySelector('canvas'):null;
|
||||
// можно ли создать webgl вручную?
|
||||
const test=document.createElement('canvas'); test.width=10; test.height=10;
|
||||
const gl=test.getContext('webgl')||test.getContext('webgl2');
|
||||
return {
|
||||
wrapW: wrap?Math.round(wrap.getBoundingClientRect().width):0,
|
||||
wrapH: wrap?Math.round(wrap.getBoundingClientRect().height):0,
|
||||
cardW: card?Math.round(card.getBoundingClientRect().width):0,
|
||||
cardH: card?Math.round(card.getBoundingClientRect().height):0,
|
||||
canvasExists: !!cv,
|
||||
canvasW: cv?cv.width:0, canvasH: cv?cv.height:0,
|
||||
canvasCssW: cv?Math.round(cv.getBoundingClientRect().width):0,
|
||||
webglWorks: !!gl,
|
||||
renderer: gl?gl.getParameter(gl.VERSION):'none',
|
||||
};
|
||||
});
|
||||
console.log(JSON.stringify({r, errs}, null, 1));
|
||||
await b.close();
|
||||
Reference in new issue
Block a user