跳转到内容
打开/关闭搜索
搜索
打开/关闭菜单
451
条目
802
文件
22
用户
9001
编辑
Blockland Wiki
导航
首页
最近更改
随机页面
MediaWiki帮助
特殊页面
打开/关闭外观设置菜单
无法加载外观设置。请检查您的网络连接并重试。
重试
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。
user-interface-preferences
个人工具
创建账号
登录
查看“︁MediaWiki:KuranokaFX.js”︁的源代码
MediaWiki界面页面
查看
阅读
查看源代码
查看历史
相关页面
系统消息
讨论
更多操作
更多
工具
链入页面
相关更改
页面信息
Cargo数据
←
MediaWiki:KuranokaFX.js
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
用户
此页面为本wiki上的软件提供界面文本,并受到保护以防止滥用。如欲修改所有wiki的翻译,请访问
translatewiki.net
上的MediaWiki本地化项目。
您无权编辑此JavaScript页面,因为编辑此页面可能会影响所有访问者。
您可以查看和复制此页面的源代码。
/* * KURANOKA / STORMBREAK v2 * File page: MediaWiki:KuranokaFX.js * Only operates on the Kuranoka view page. Never rewrites / filters article text. * Canvas-based cinematic storm / rain / spatial tear / glass rifts / clearing. */ (function () { 'use strict'; if (window.__kkStormbreakLoaded) return; if (window.mw && ( mw.config.get('wgPageName') !== 'Kuranoka' || mw.config.get('wgAction') !== 'view' || mw.config.get('wgNamespaceNumber') !== 0 )) return; function start() { var ids = ['kk-fx-start','kk-fx-rift','kk-fx-void','kk-fx-clear']; var markers = ids.map(function(id) { return document.getElementById(id); }); if (markers.some(function(e) { return !e; })) return; window.__kkStormbreakLoaded = true; document.documentElement.classList.add('kk-stormbreak-enabled'); var canvas = document.createElement('canvas'); canvas.id = 'kk-stormbreak-canvas'; canvas.setAttribute('aria-hidden','true'); var veil = document.createElement('div'); veil.id = 'kk-stormbreak-atmosphere'; veil.setAttribute('aria-hidden','true'); // Put FX outside article. Never wrap, filter, scale or re-style article DOM. document.body.appendChild(veil); document.body.appendChild(canvas); var ctx = canvas.getContext('2d', { alpha: true }); if (!ctx) return; var ctrl = document.createElement('div'); ctrl.id = 'kk-stormbreak-controls'; ctrl.innerHTML = '<span aria-hidden="true">◈ STORMBREAK</span>' + '<label for="kk-stormbreak-power">强度</label>' + '<input id="kk-stormbreak-power" type="range" min="25" max="100" value="100" step="5" aria-label="调整特效强度">' + '<button type="button" id="kk-stormbreak-toggle" aria-pressed="false">关闭特效</button>'; document.body.appendChild(ctrl); var slider = ctrl.querySelector('input'); var button = ctrl.querySelector('button'); var media = window.matchMedia ? window.matchMedia('(prefers-reduced-motion: reduce)') : null; var disabled = !!(media && media.matches); var power = 1; var dpr = 1, w = 0, h = 0; var lastTime = 0, raf = 0, ticking = false, active = false; var geom = [], drops = []; var pos = []; var probe = { intensity:0, storm:0, rift:0, void:0, clear:0 }; function clamp(n, a, b) { return Math.max(a, Math.min(b, n)); } function smooth(a,b,x) { if (b<=a) return x>=b ? 1 : 0; var t=clamp((x-a)/(b-a),0,1); return t*t*(3-2*t); } function rng(seed) { return function () { seed |= 0; seed = seed+0x6D2B79F5|0; var t=Math.imul(seed^(seed>>>15),1|seed); t=t+Math.imul(t^(t>>>7),61|t)^t; return ((t^(t>>>14))>>>0)/4294967296; }; } var random = rng(2241984); for (var i=0;i<95;i++) drops.push({x:random(),y:random(),v:.7+random()*1.5,len:12+random()*40,weight:.45+random()*1.7}); for (var j=0;j<18;j++) geom.push({x:random(),y:random(),len:random(),phase:random()*6.28}); function measure() { dpr = Math.min(window.devicePixelRatio||1, window.innerWidth < 700 ? 1.2 : 1.5); w = Math.max(1,window.innerWidth); h=Math.max(1,window.innerHeight); canvas.width=Math.round(w*dpr); canvas.height=Math.round(h*dpr); canvas.style.width=w+'px'; canvas.style.height=h+'px'; ctx.setTransform(dpr,0,0,dpr,0,0); pos = markers.map(function(el) {return el.getBoundingClientRect().top+window.scrollY;}); } function updateScroll() { ticking=false; var center=window.scrollY+h*.55; var s=pos[0], r=pos[1], v=pos[2], c=pos[3]; var inChapter=center>=s-h*.35 && center<c+h*.72; document.documentElement.classList.toggle('kk-stormbreak-inchapter',inChapter); if (disabled) { disableVisuals(); return; } var enter=smooth(s-h*.35,s+h*.32,center); var leave=1-smooth(c+h*.05,c+h*.94,center); var intensity=enter*leave*power; probe.intensity=intensity; probe.storm=smooth(s+h*.05, r, center); probe.rift=smooth(r-h*.1, v, center); probe.void=smooth(v-h*.18, v+h*.42, center); probe.clear=smooth(c-h*.45,c+h*.25, center); active=intensity>.008; document.documentElement.classList.toggle('kk-stormbreak-active',active); veil.style.setProperty('--kk-atmosphere',String(clamp(intensity*(.78+.24*probe.void)*(1-.98*probe.clear),0,1))); if (active && !raf) raf=window.requestAnimationFrame(tick); } function scrollListener() { if (!ticking) {ticking=true; requestAnimationFrame(updateScroll);} } function disableVisuals() { active=false; document.documentElement.classList.remove('kk-stormbreak-active'); veil.style.setProperty('--kk-atmosphere','0'); ctx.clearRect(0,0,w,h); button.textContent='开启特效'; button.setAttribute('aria-pressed','true'); } function setEnabled() { button.textContent=disabled ? '开启特效' : '关闭特效'; button.setAttribute('aria-pressed',String(disabled)); updateScroll(); } button.addEventListener('click',function(){ disabled=!disabled; setEnabled(); }); slider.addEventListener('input',function(){ power=Number(slider.value)/100; updateScroll(); }); if (media && media.addEventListener) media.addEventListener('change',function(e){disabled=e.matches; setEnabled();}); function gradEllipse(x,y,rX,rY,inner,outer,alpha) { ctx.save();ctx.translate(x,y);ctx.scale(1,rY/rX); var g=ctx.createRadialGradient(0,0,0,0,0,rX); g.addColorStop(0,inner);g.addColorStop(1,outer); ctx.globalAlpha=alpha;ctx.fillStyle=g; ctx.beginPath();ctx.arc(0,0,rX,0,Math.PI*2);ctx.fill();ctx.restore(); } function linePath(points,color,width,alpha) { ctx.save();ctx.globalAlpha=alpha;ctx.lineWidth=width;ctx.strokeStyle=color; ctx.lineCap='round';ctx.lineJoin='round';ctx.beginPath(); points.forEach(function(p,i){if(i===0)ctx.moveTo(p[0],p[1]);else ctx.lineTo(p[0],p[1]);}); ctx.stroke();ctx.restore(); } function drawClouds(t, strength) { // Storm walls press inward from all four sides, leaving the article's central text clear. var n=24; for (var i=0;i<n;i++) { var side=i%4, a=i/n*7.2, xx,yy; var drift=Math.sin(t*.00018+i*3.4)*28; if(side===0){xx=((i*109)%w)+drift;yy=-45+Math.sin(a)*75;} if(side===1){xx=w+55+drift;yy=((i*153)%h);} if(side===2){xx=((i*159)%w)+drift;yy=h+15+Math.sin(a)*90;} if(side===3){xx=-55+drift;yy=((i*149)%h);} var r=160+((i*71)%190); var color=i%3===0?'rgba(78,18,103,.51)':'rgba(9,38,115,.57)'; gradEllipse(xx,yy,r,r*.46,color,'rgba(4,9,22,0)',strength*1.15); } gradEllipse(w*.51,h*.52,w*.58,h*.54,'rgba(6,14,40,.23)','rgba(6,14,40,0)',strength*.65); } function drawRain(t, strength) { ctx.save();ctx.beginPath();ctx.rect(0,0,w,h);ctx.clip(); var offset=t*.095; for(var i=0;i<drops.length;i++) { var d=drops[i], px=d.x*w, py=((d.y*h+offset*d.v)%(h+100))-50; var edge=Math.abs(px-w/2)/(w/2); var a=(.11+.6*Math.pow(edge,1.6))*strength; ctx.strokeStyle=i%8===0?'rgba(175,110,192,'+a+')':'rgba(115,182,238,'+a+')'; ctx.lineWidth=d.weight; ctx.beginPath();ctx.moveTo(px,py);ctx.lineTo(px-9-d.len*.15,py+d.len);ctx.stroke(); }ctx.restore(); } function drawSignal(t, strength) { // 180 BPM concept is translated to an ECG-like trace running around the edges, // with NO rapid full-screen flashes and NO article text modifications. var yy=h*.84, seg=17, points=[]; var shift=(t*.055)%(w+140); for (var x=-140;x<=w+150;x+=seg) { var u=(x+shift)%185; var peak= u>75&&u<90 ? -50*Math.sin((u-75)/15*Math.PI):0; var y=yy+Math.sin(x*.018+t*.0013)*3+peak; points.push([x,y]); } linePath(points,'#69d6ed',1.5,strength*.7); linePath(points.map(function(p){return [p[0]+4,p[1]+1];}),'#e65d91',1.2,strength*.36); // Blunt angular bands, suggesting a mismatched signal. ctx.save();ctx.globalAlpha=strength*.75; ctx.fillStyle='rgba(218,74,111,.28)'; var k=Math.floor(t/220); for(var i=0;i<7;i++){ var seed=(k*19+i*317)>>>0, xx=((seed*73)%1301)/1301*w; var y=((seed*139)%997)/997*h; var rw=35+(seed%100); ctx.fillRect(xx,y,rw,2+seed%5); }ctx.restore(); } function drawFracture(t, strength) { // Large static-ish fractures, spanning view edges (never filters text). var centers=[[-w*.08,h*.23],[w*1.06,h*.42],[w*.47,-h*.13],[w*.58,h*1.08]]; var now=Math.sin(t*.0006); centers.forEach(function(base,index){ var local=rng(24111+index*441); var maxR=Math.min(w,h)*(.60 + .13*index); var points=[]; var heading=(index*1.57)+.06; for(var j=0;j<9;j++) { var rad=j/8*maxR; var a=heading+Math.sin(j*.63+index)*.42+(local()-.5)*.2; points.push([base[0]+Math.cos(a)*rad,base[1]+Math.sin(a)*rad]); } linePath(points,'rgba(9,13,37,1)',8,strength*.75); linePath(points,'#88d8f8',2.5,strength*(.92+now*.06)); linePath(points.map(function(p){return[p[0]+5,p[1]-2];}),'#fe638e',1.9,strength*.93); for(var k=2;k<8;k+=2) { var c=points[k], b=points[Math.min(k+1,8)], a=Math.atan2(b[1]-c[1],b[0]-c[0])+((k%4)?1:-1)*.8; var len=40+local()*100; linePath([c,[c[0]+Math.cos(a)*len,c[1]+Math.sin(a)*len]],'#a1b6f0',.8,strength*.55); } }); // Screen-tear slices shift translucent atmosphere only (never page DOM). var index=Math.floor(t/360); var tear=rng(index*5923+772); for(var z=0;z<7;z++){ var ty=tear()*h, tw=40+tear()*Math.min(w*.45,380), tx=tear()*w; ctx.save();ctx.globalAlpha=strength*(.18+tear()*.28); ctx.fillStyle=z%2?'#ff4b90':'#34bde3'; ctx.fillRect(tx,ty,tw,4+tear()*18); ctx.restore(); } } function drawAbyss(t, strength) { // A ring / distorted horizon instead of replacing or morphing paragraphs. var cx=w*.5,cy=h*.49,base=Math.max(w,h)*.46; gradEllipse(cx,cy,base,base*.74,'rgba(4,4,19,.14)','rgba(4,4,19,0)',strength); var rings=3; for (var ring=0;ring<rings;ring++) { ctx.save();ctx.translate(cx,cy);ctx.scale(1,.70); var radius=base*(.72+ring*.17)+Math.sin(t*.00048+ring)*7; ctx.strokeStyle=ring===1?'rgba(255,55,121,.82)':'rgba(68,197,255,.58)'; ctx.lineWidth=ring===1?3.4:2; ctx.globalAlpha=strength; ctx.beginPath(); for(var a=0;a<Math.PI*2;a+=.035) { var rr=radius+Math.sin(a*13+t*.00054+ring)*7+Math.cos(a*37+ring)*4; if(a===0) ctx.moveTo(Math.cos(a)*rr,Math.sin(a)*rr); else ctx.lineTo(Math.cos(a)*rr,Math.sin(a)*rr); }ctx.closePath();ctx.stroke();ctx.restore(); } // Staggered geometric shards in peripheral vision. ctx.save();ctx.globalAlpha=strength*.7; for(var i=0;i<geom.length;i++){ var d=geom[i];var x=d.x*w,y=d.y*h; var edge=Math.max(Math.abs(d.x-.5)*2,Math.abs(d.y-.5)*2); if(edge<.55)continue; var spread=20+d.len*85; var sway=Math.sin(t*.00032+d.phase)*8; ctx.fillStyle=i%3?'rgba(80,145,232,.09)':'rgba(232,59,112,.13)'; ctx.strokeStyle=i%2?'rgba(114,195,252,.35)':'rgba(243,93,148,.3)'; ctx.lineWidth=1.0; ctx.beginPath();ctx.moveTo(x+sway,y-spread);ctx.lineTo(x+spread*.9+sway,y+spread*.3);ctx.lineTo(x-spread*.4+sway,y+spread);ctx.closePath();ctx.fill();ctx.stroke(); }ctx.restore(); } function drawClear(t, strength) { // Light begins to reclaim the storm without a full-screen white flash. ctx.save();ctx.globalAlpha=strength; for(var i=0;i<9;i++){ var x=w*.27+i*w*.075; var g=ctx.createLinearGradient(x-150,-100,x+50,h+100); g.addColorStop(0,'rgba(119,213,255,.0)'); g.addColorStop(.30,'rgba(145,224,255,.14)'); g.addColorStop(.7,'rgba(126,201,255,.045)'); g.addColorStop(1,'rgba(160,237,255,0)'); ctx.fillStyle=g; ctx.beginPath();ctx.moveTo(x-22,-60);ctx.lineTo(x+26,-60);ctx.lineTo(x+220,h+60);ctx.lineTo(x+80,h+60);ctx.fill(); } for(var j=0;j<40;j++){ var p=drops[j], px=p.x*w, py=((p.y*h -t*.022*p.v)%(h+60)+h+60)%(h+60); ctx.fillStyle='rgba(181,230,255,'+(.08+.2*((j%9)/9))+')'; ctx.fillRect(px,py,1.2,1.2); }ctx.restore(); } function render(t) { ctx.clearRect(0,0,w,h); var q=probe, mag=q.intensity; if(mag<=.008) return; var intensity=Math.min(1,mag); drawClouds(t,intensity*(.72+.9*q.storm)*(1-q.clear*.93)); drawRain(t,intensity*(.6+.8*q.rift)*(1-q.clear*.97)); drawSignal(t,intensity*smooth(.25,.75,q.rift)*(.8+.3*q.void)*(1-q.clear)); drawFracture(t,intensity*q.rift*(1-q.clear*.98)); drawAbyss(t,intensity*q.void*(1-q.clear*.98)); if(q.clear>0) drawClear(t,intensity*q.clear); } function tick(t) { raf=0; if(!active||disabled||document.hidden) return; // 30 FPS cap, plus device-pixel-ratio cap, for CPU-friendly effects. if(t-lastTime>=32){ lastTime=t;render(t); } raf=requestAnimationFrame(tick); } window.addEventListener('scroll',scrollListener,{passive:true}); window.addEventListener('resize',function(){measure();updateScroll();},{passive:true}); window.addEventListener('load',function(){measure();updateScroll();},{once:true}); document.addEventListener('visibilitychange',function(){if(!document.hidden)updateScroll();}); measure(); setEnabled(); } if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',start,{once:true}); else start(); }());
返回
MediaWiki:KuranokaFX.js
。
查看“︁MediaWiki:KuranokaFX.js”︁的源代码
MediaWiki界面页面