繁体   English   中英

div逐渐淡出侧面

[英]div gradually fading out on side

很难解释,所以让我们看一下这张照片:

在此处输入图片说明

如您所见,图像中心有一个渐变的规则。 我正在尝试使用HTML / CSS找到实现的方法。

我的问题是:

  1. 背景图像 (这里是棒球比赛) 可以随时更改 ,因此标尺在透明背景上需要为白色。
  2. 尺子两边都褪色
  3. 可以对标尺进行动画处理 (以查看其标记滚动)

我的猜测是使用HTML / CSS是不可能的。 我想知道是否有人知道使用JS和Canvas(或任何前端技术)实现此目标的方法?

编辑:我不好,我忘了提到必须与IE9及更高版本一起使用。

我发现使用javascript和canvas做这样的事情很容易。

只需创建DOM元素即可,该元素包含您想要覆盖的内容,并将覆盖设置设为数据属性。 例如data-ticks-tick-width = "2"

然后在window.onload ,使用要覆盖的元素的ID以及您可能希望覆盖的所有设置调用该函数。 您将获得一个包含该设置的对象(如果您刚刚使用默认值,现在可以访问),并且如果想要更改任何设置或具有悬停效果,则可以使用一种方法重画画布。 您可以根据需要执行任意多个元素。 您也可以只在DOM中搜索具有data-ticks属性的元素,然后以这种方式添加画布。

演示展示了一种方法。

 var addTicks = function(container, settings){ var name, defaults, step, ctx, canvas, location, x, y, w, h, tickCount; function getSetting(dataName){ var val; if(container.attributes["data-" + name + "-" + dataName] !== undefined){ val = container.attributes["data-" + name + "-" + dataName].value; }else if(settings[defaults[dataName][1]] !== undefined){ val = settings[defaults[dataName][1]]; }else{ val = defaults[dataName][0]; } return settings[defaults[dataName][1]] = val; } function easeBell(x, pow) { // x = x*2; if( x > 1){ x = 1-(x-1); var xx = Math.pow(x,pow); return(xx/(xx+Math.pow(1-x,pow))) }else{ var xx = Math.pow(x,pow); return(xx/(xx+Math.pow(1-x,pow))) } } function createCanvas(){ canvas = document.createElement("canvas"); canvas.style.position = "absolute"; canvas.style.zIndex = settings.zIndex; container.appendChild(canvas); } function resize(){; if(canvas === undefined){ createCanvas(); } location = container.getBoundingClientRect(); y = location.top; x = location.left; w = (location.right - location.left); h = (location.bottom - location.top); canvas.width = Math.round(w * settings.width); canvas.height = Math.round(h * settings.height); canvas.style.left = (x+Math.round((w - canvas.width)/2)) + "px"; canvas.style.top = (y+Math.round((h - canvas.height)/2)) + "px"; ctx = canvas.getContext("2d"); ctx.strokeStyle = settings.color; ctx.lineCap = "butt"; tickCount = Math.floor((canvas.width / settings.spacing) / 2); draw(); } function draw(){ var i, cx, cy, th, step; step = settings.spacing; i = 0; cx = canvas.width / 2; cy = canvas.height / 2; ctx.clearRect(0,0,canvas.width,canvas.height) ctx.lineWidth = settings.tickWidth; for(i = 0; i < tickCount; i ++){ ctx.beginPath(); if(i === 0){ ctx.moveTo(cx, cy - settings.majorHeight / 2); ctx.lineTo(cx, cy + settings.majorHeight / 2); }else{ if((i % settings.majorEvery) === 0){ th = settings.majorHeight / 2; }else{ th = settings.minorHeight / 2; } ctx.globalAlpha = easeBell(1- i / tickCount,settings.falloff); ctx.moveTo(cx + i * step, cy - th); ctx.lineTo(cx + i * step, cy + th); ctx.moveTo(cx - i * step, cy - th); ctx.lineTo(cx - i * step, cy + th); } ctx.stroke(); } } name = "ticks"; defaults = { width : [0.5,"width"], height : [0.2,"height"], 'spacing' : [10,"spacing"], 'major-height' : [20,"majorHeight"], 'minor-height' : [10,"minorHeight"], 'major-every' : [5,"majorEvery"], 'color' : ["white","color"], 'z-index' : [1000,"zIndex"], 'tick-width' : [2,"tickWidth"], 'falloff' : [2,"falloff"], }; if(typeof container === "string"){ container = document.querySelector("#" + container); } if(container === null || container === undefined){ return undefined; } if(settings === undefined){settings = {};} "width,height,spacing,major-height,minor-height,major-every,color,z-index,tick-width,tick-width,falloff" .split(",") .forEach(getSetting); window.addEventListener("resize",resize); resize(); return { canvas : canvas, redraw : resize, settings : settings, }; } var ticksForImage1; window.addEventListener("load",function(){ ticksForImage1 = addTicks("imgContainer"); }); 
 img { width : 100%; height : 100%; } 
 <div id="imgContainer" data-ticks-color="#EFE" data-ticks-tick-width="1" data-ticks-width='0.9')><img id= "myImage" src='https://upload.wikimedia.org/wikipedia/commons/thumb/0/01/After_Plotting_Rice_Plant.jpg/1280px-After_Plotting_Rice_Plant.jpg' title='By Punya - Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=35038411'></div> 

更新

动画演示。 这是一种快速技巧,而不是解决动画的最佳方法。 作为设置动画补间和使用requestAnimationFrame进行渲染的示例。

增加的属性

data-ticks-animate = 'true'  
data-ticks-start-in = '2000' 
data-ticks-run-for = '4000'  
data-ticks-end... animated attributes. see code for list

 var addTicks = function(container, settings){ var name, defaults, step, ctx, canvas, location, x, y, w, h, tickCount, settingsEnd,currentSettings ; var settingsAtr = "width,height,spacing,major-height,minor-height,major-every,color,z-index,tick-width,animate,start-in,run-for".split(","); var animSettingsAtrInt = "majorEvery".split(","); var animSettingsAtr = "spacing,majorHeight,minorHeight,tickWidth".split(","); function getSetting(dataName){ var val; if(container.attributes["data-" + name + "-" + dataName] !== undefined){ val = container.attributes["data-" + name + "-" + dataName].value; }else if(settings[defaults[dataName][1]] !== undefined){ val = settings[defaults[dataName][1]]; }else{ val = defaults[dataName][0]; } return settings[defaults[dataName][1]] = val; } function easeInOut(x, pow) { var xx = Math.pow(Math.min(1, Math.max(0, x)), pow); return(xx / (xx + Math.pow(1 - x, pow))) } function createCanvas(){ canvas = document.createElement("canvas"); canvas.style.position = "absolute"; canvas.style.zIndex = settings.zIndex; container.appendChild(canvas); } function resize(){ if(canvas === undefined){ createCanvas(); } location = container.getBoundingClientRect(); y = location.top; x = location.left; w = (location.right - location.left); h = (location.bottom - location.top); canvas.width = Math.round(w * settings.width); canvas.height = Math.round(h * settings.height); canvas.style.left = (x+Math.round((w - canvas.width)/2)) + "px"; canvas.style.top = (y+Math.round((h - canvas.height)/2)) + "px"; ctx = canvas.getContext("2d"); if(!settings.animate ){ draw(settings); }else{ startAnim(); } } function draw(settings){ var i, cx, cy, th, step; step = Math.max(1,settings.spacing); ctx.strokeStyle = settings.color; ctx.lineCap = "butt"; tickCount = Math.floor((canvas.width / step) / 2); i = 0; cx = canvas.width / 2; cy = canvas.height / 2; ctx.clearRect(0,0,canvas.width,canvas.height) ctx.lineWidth = settings.tickWidth; for(i = 0; i < tickCount; i ++){ ctx.beginPath(); if(i === 0){ ctx.globalAlpha = 1; ctx.moveTo(cx, cy - settings.majorHeight / 2); ctx.lineTo(cx, cy + settings.majorHeight / 2); }else{ if((i % settings.majorEvery) === 0){ th = settings.majorHeight / 2; }else{ th = settings.minorHeight / 2; } ctx.globalAlpha = easeInOut(1- i / tickCount,2); ctx.moveTo(cx + i * step, cy - th); ctx.lineTo(cx + i * step, cy + th); ctx.moveTo(cx - i * step, cy - th); ctx.lineTo(cx - i * step, cy + th); } ctx.stroke(); } } var endTime; var runTime; function animate(time){ if(endTime === undefined){ endTime = time + Number(settings.runFor); } var progress = 1-Math.min(1,(endTime - time) / Number(settings.runFor)); for(var i= 0; i < animSettingsAtrInt.length; i ++){ var f = Number(settings[animSettingsAtrInt[i]]); var t = Number(settingsEnd[animSettingsAtrInt[i]]); currentSettings[animSettingsAtrInt[i]] = Math.floor((tf) * progress + f); } for(var i= 0; i < animSettingsAtr.length; i ++){ var f = Number(settings[animSettingsAtr[i]]); var t = Number(settingsEnd[animSettingsAtr[i]]); currentSettings[animSettingsAtr[i]] = (tf) * progress + f; } draw(currentSettings); if(progress < 1){ requestAnimationFrame(animate) } } function start(){ requestAnimationFrame(animate); } function startAnim(){ endTime = undefined; setTimeout(start,Number(settings.startIn)); } name = "ticks"; defaults = { width : [0.5,"width"], height : [0.2,"height"], 'spacing' : [10,"spacing"], 'major-height' : [20,"majorHeight"], 'minor-height' : [10,"minorHeight"], 'major-every' : [5,"majorEvery"], 'color' : ["white","color"], 'z-index' : [1000,"zIndex"], 'tick-width' : [5,"tickWidth"], 'animate' : [true,"animate"], 'start-in' : [2000, "startIn"], 'run-for' : [5000, "runFor"] }; if(typeof container === "string"){ container = document.querySelector("#" + container); } if(container === null || container === undefined){ return undefined; } if(settings === undefined){settings = {};} settingsAtr.forEach(getSetting); var tempSettings = settings; settings = {}; settingsAtr.forEach(getSetting); currentSettings = settings; settings = tempSettings; if(settings.animate){ name = "ticks-end"; var settingT = settings; settings = {}; settingsAtr.forEach(getSetting); settingsEnd = settings; settings = settingT; name = "ticks"; } window.addEventListener("resize",resize); resize(); return { canvas : canvas, redraw : resize, settings : settings, }; } var ticksForImage1; window.addEventListener("load",function(){ ticksForImage1 = addTicks("imgContainer"); }); 
 img { width : 100%; height : 100%; } 
 <div id="imgContainer" data-ticks-animate='true' data-ticks-start-in='2000' data-ticks-run-for='4000' data-ticks-spacing='50' data-ticks-end-spacing='20' data-ticks-major-height='10' data-ticks-end-major-height='30' data-ticks-minor-height='30' data-ticks-end-minor-height='10' data-ticks-tick-width='12' data-ticks-end-tick-width='1' data-ticks-color="#FFF"><img id= "myImage" src='https://upload.wikimedia.org/wikipedia/commons/thumb/0/01/After_Plotting_Rice_Plant.jpg/1280px-After_Plotting_Rice_Plant.jpg'></div> 

您实际上确实有一个CSS选项,但是现在它的支持相当不稳定。 我说的是mask属性。 在我撰写本文时,IE和Edge不支持它们,Webkit和moz浏览器也不同地支持它们,但是基本上对于wbekit,您具有:

-webkit-mask-image: -webkit-gradient(linear, left top, right top, from(rgba(0,0,0,1)), color-stop(0.75, rgba(0,0,0,1)), to(rgba(0,0,0,0)));

对于moz,您需要将SVG图形与CSS结合使用:

mask: url(#fade_right_svg_mask);

例子取自这里

使用画布的简单步骤(循环):

  • 背景清晰
  • 使用fillRect()使用pattern + translate或lines + stroke()在正确的偏移位置绘制标尺。 复合模式“ source-over
  • 使用具有透明边缘的线性(或径向)渐变或代表蒙版的图像在顶部绘制版。 复合模式“ destination-in
  • 使用复合模式“ destination-atop ”在顶部绘制背景图像

卡

根据需要调整线条和颜色(尽管渐变只影响alpha)。 这只是一个粗略的骨架-根据需要采用:

 var ctx = c.getContext("2d"), x = 0; // pseudo ruler for demo ctx.globalCompositeOperation = "source-over"; // needed if in a loop ctx.beginPath(); for(var i=30;i--;) {ctx.moveTo(i*10+0.5, 60);ctx.lineTo(i*10+0.5, 90)} ctx.strokeStyle = "#fff"; ctx.stroke(); // mask var gr = ctx.createLinearGradient(0,0,300,0); gr.addColorStop(0, "rgba(0,0,0,0)"); gr.addColorStop(0.5, "#000"); gr.addColorStop(1, "rgba(0,0,0,0)"); ctx.fillStyle = gr; ctx.globalCompositeOperation = "destination-in"; ctx.fillRect(0,0,300,150); // draw background image ctx.globalCompositeOperation = "destination-atop"; ctx.fillStyle = "#07f"; ctx.fillRect(0,0,300,150); 
 <canvas id=c></canvas> 

提示:如果线性渐变在IE9中产生问题,请用蒙版图像替换它。 如果可以,我建议缓存渐变。 定义它并不会花费很多,但是渲染会花费很多,因此将其渲染到屏幕外的画布上,然后将该画布用作drawImage()的图像源即可。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM