有很多方法可以做到这一点,已经建议使用 CSS3 和图像,所以我建议使用画布。
HTML 画布元素内置了您需要的一切。它允许渐变背景填充,并且使用globalCompositeOperation,可以对形状和文本进行遮罩,在背景中创建切口以使真正的可变 HTML 元素在彩色背景下真正透明。它也可以很好地扩展,并且可以很容易地做出响应。
所有主流浏览器都支持 canvas 元素,除了 Internet Explorer 8 及更低版本,这意味着浏览器支持比前面提到的许多 CSS3 方法更好,比如关键帧和背景大小。
使用后备,比如在画布不可用时淡入淡出的图像,应该不会很难弄清楚,并且在除 Internet Explorer 9 以下的所有其他浏览器中,不需要图像来创建渐变画布中的背景和文本掩码,这应该会使页面的加载速度显着加快。
要检测是否支持画布,您可以使用这个方便的功能:
function isCanvasSupported(){
var elem = document.createElement('canvas');
return !!(elem.getContext && elem.getContext('2d'));
}
像这样使用:
if ( isCanvasSupported() ) {
// do canvas stuff
}else{
// fall back to images
}
所以,让我们开始吧!要创建“最后的手段”后备和一些我们可以“克隆”到画布中的元素,我们将在 HTML 中创建我们需要的元素,以获得类似于您在问题中概述的结构。这具有额外的优势,即能够仅更改一些 CSS 以在画布中进行更改:
<div id="gradient">
<div class="text">COMPANY NAME</div>
<div class="h_bar"></div>
<div class="v_bar"></div>
</div>
它只是一个容器,其中包含一个文本元素,每个条都有一个元素。
一些样式也是必要的,我会用简单的方法来做,有位置absolute
和一些非常快速的定位,因为除非有人禁用了 javascript,否则这些元素将不可见:
#gradient {position: absolute;
background: #000;
top: 5%; left: 5%; right: 5%; bottom: 5%;
}
.text {position: absolute;
top: 20px;
left: 100px;
width: 400px;
color: #fff; font-size: 40px; font-weight: bold;
font-family: arial, verdana, sans-serif;
}
.h_bar {position: absolute;
height: 20px;
top: 100px; left: 60px; right: 60px;
background: #fff;
}
.v_bar {position: absolute;
width: 20px;
top: 140px; bottom: 30px; right: 60px;
background: #fff;
}
没有任何看起来完全像THIS FIDDLE的 javascript ,它应该有点响应并适应窗口大小。
现在我们需要一些 javascript 来将这些元素变成画布中的东西。我们将创建两个画布元素,一个用于背景,因为我决定在随机渐变之间连续设置背景动画,另一个用于内部黑框和内容(文本和条形图)。
由于文本和条的遮罩可能有点慢,我们不必重绘所有内容,只需重新绘制背景画布,因为前景是相当静态的。这也避免了某些高帧率浏览器中的闪烁问题,我们将使用 requestAnimationFrame 作为背景画布的动画,因此如果我们不使用两个画布元素,文本掩码中的闪烁将是一个问题。
对于不支持 requestAnimationFrame 的浏览器,我们将添加这个 polyfill以确保它可以在任何地方工作。
是时候写一些 javascript 了,这当然使用 jQuery :
var gradSite = {
init: function() {
var self = this;
self.create().setSizes().events();
(function animationloop(){
requestAnimationFrame(animationloop);
self.draw().colors.generate();
})();
},
create: function() { // creates the canvas elements
this.canvas = document.createElement('canvas');
this.canvas2 = document.createElement('canvas');
this.canvas.id = 'canvas1';
this.canvas2.id = 'canvas2';
this.canvas.style.position = 'absolute';
this.canvas2.style.position = 'absolute';
$('#gradient').after(this.canvas, this.canvas2);
return this;
},
events: function() { //event handlers
$(window).on('resize', this.setSizes);
$('#gradient').on('contentchange', this.draw2);
return this;
},
setSizes: function() { // sets sizes on load and resize
var self = gradSite,
w = $(window),
m = $('#gradient');
self.canvas.height = w.height();
self.canvas.width = w.width();
self.canvas2.bg = m.css('background-color');
self.canvas2.height = m.height();
self.canvas2.width = m.width();
self.canvas2.style.top = m.offset().top + 'px';
self.canvas2.style.left = m.offset().left + 'px';
self.draw2();
return self;
},
colors: {
colors: {
0: [255,255,0],
1: [255,170,0],
2: [255,0,0]
},
map: {
0: [0,0,1],
1: [0,1,1],
2: [0,1,1]
},
generate: function() { // generates the random colors
var self = this;
$.each(self.colors, function(i,color) {
$.each(color, function(j, c) {
var r = Math.random(),
r2 = Math.random(),
val = self.map[i][j] == 0 ? (c-(j+r)) : (c+(j+r2));
if (c > 255) self.map[i][j] = 0;
if (c < 0 ) self.map[i][j] = 1;
self.colors[i][j] = val;
});
});
}
},
raf: (function() { // polyfill for requestAnimationFrame
var lastTime = 0,
vendors = ['webkit', 'moz'];
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame)
window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime(),
timeToCall = Math.max(0, 16 - (currTime - lastTime)),
id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall);
lastTime = currTime + timeToCall;
return id;
};
if (!window.cancelAnimationFrame)
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}()),
calculateColor: function(colors) { // returns a rgb color from the array
return 'rgb(' + Math.round(colors[0]) + ',' + Math.round(colors[1]) + ',' + Math.round(colors[2]) + ')';
},
draw: function() { //draws the color background
var self = this,
c = self.canvas || document.getElementById('canvas1'),
ctx = c.getContext('2d'),
grad = ctx.createLinearGradient(0,0,0,self.canvas.height);
c.width = c.width;
grad.addColorStop(0, self.calculateColor(self.colors.colors[0]));
grad.addColorStop(0.5, self.calculateColor(self.colors.colors[1]));
grad.addColorStop(1, self.calculateColor(self.colors.colors[2]));
ctx.fillStyle = grad;
ctx.fillRect(0,0,self.canvas.width, self.canvas.height);
return self;
},
draw2: function() { // draws the black square and content
var self = this,
c = self.canvas2 || document.getElementById('canvas2'),
ctx2 = c.getContext('2d'),
txt = $('.text', '#gradient').first(),
hbar = $('.h_bar', '#gradient').first(),
vbar = $('.v_bar', '#gradient').first();
c.width = c.width;
ctx2.globalCompositeOperation = 'xor';
ctx2.font = txt.css('font');
ctx2.fillStyle = c.bg || '#000';
ctx2.fillText(txt.text(), txt.offset().left, txt.offset().top);
ctx2.fillRect(hbar.position().left, hbar.position().top, hbar.width(),hbar.height());
ctx2.fillRect(vbar.position().left, vbar.position().top, vbar.width(),vbar.height());
ctx2.fillRect(0,0,c.width,c.height);
}
}
该raf
函数将是 requestAnimationFrame 的 polyfill,两个绘制函数在画布中创建内容。真的没那么复杂。
我们将在 DOM 就绪处理程序中调用上述脚本,如下所示:
$(function() {
gradSite.init(); // starts the canvas stuff
});
将所有这些添加到小提琴中,并添加一些用于演示目的的元素,它看起来像THIS FIDDLE,这是完成的 ->
全屏演示