今年年初时我偶然看到了下面这张图片,顺手把它记在了微博里,近日抽时间把它们制作成了交互页面,本文记录了开发的过程。
效果预览
按下右侧的“点击预览”按钮可以在当前页面预览,点击链接可以全屏预览。
源代码下载
每日前端实战系列的全部源代码请从 github 下载:
代码解读
一、准备素材
二、DOM 结构
容器名为 .person,表示一个人的外貌,它包含一个子元素 .inside,表示这个人被透视出的身体内部,就是骨骼、血管什么的啦。
三、呈现人的正常状态
令元素在页面居中显示:body {
margin: 0;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
把图片 css.png 作为容器 .person 的背景图:.person {
width: 320px;
height: 537px;
background-image: url(css.png);
}
效果如下图:
四、呈现人的骨骼
把图片 html.png 作为元素 .person .inside 的背景图。.person .inside {
width: 100%;
height: 100%;
background-image: url(html.png);
background-position: center;
}
效果如下图:
为图片加上 5px 的灰色边框。.person .inside {
box-sizing: border-box;
border: 5px solid gray;
border-radius: 0.3em;
}
效果如下图:
缩小边框的高度为 100px,并定位在容器的中上位置,这是未来上下滑动的透视窗。.person {
position: relative;
}
.person .inside {
/*height: 100%;*/
height: 100px;
position: absolute;
top: 25%;
}
效果如下图:
仔细看上图,是有错误的,透视窗处于人的胸部,但透视出的区域是人的腰部。所以需要用 background-attachment: fixed; 把图片锁定在固定位置。请留意,这个属性值是整个作品的核心,否则不会有透视窗滑动的效果。.person .inside {
background-attachment: fixed;
}
效果如下图:
至此,静态布局完成。
五、透视窗滑动效果
接下来处理透视窗跟随鼠标的滑动效果。
程序入口是 init 函数,在其中声明2个变量 person 和 inside,分别代表它们对应的 DOM 元素。window.onload = init
function init() {
var person = document.querySelector('.person')
var inside = document.querySelector('.person .inside')
}
为 person 元素绑定 mousemove 事件,当事件被触发时,更新 inside 元素的 top 属性值,形成滑动效果。function init() {
person.addEventListener('mousemove', function (e) {
inside.style.top = getTopPosition(e.offsetY)
});
}
top 的属性值通过 getTopPosition() 函数计算得来,其中 offset 值为透视窗高度的一半,意为透视窗在滑动时,鼠标指针位于透视窗的中间位置。在检测了滑动的位置没有跑到容器外面之后,返回位置,这里要加上单位 px。function getTopPosition(y) {
const windowHeight = 100
var offset = windowHeight / 2
if(y < offset) return
if(y > (Number.parseInt(window.getComputedStyle(person).height)) - offset) return
return y - offset + 'px'
}
现在刷新页面,看到已经有滑动效果了,但是非常不流畅,这是因为子元素 .inside 位于容器 .person 之上,会先触发子元素的事件,为此,我们用 pointer-events: none; 禁止子元素响应鼠标事件。
另外,把鼠标指针显示为表示可移动的图标。.person {
cursor: move;
}
.person .inside {
pointer-events: none;
}
至此,本作品的核心功能开发完成了。
六、切换透视图
接下来增加切换透视内容的功能。
在 DOM 中增加 2 个复选框,用于选择是透视 html(人体骨骼),还是透视 js(人体神经)。
HTML
JavaScript
定义复选框的样式,这不是本作品的重点,用的也是普通的属性,就不作详细讲解了。.selector {
position: absolute;
width: 9em;
top: calc(50% - 8em / 2);
left: 3em;
display: grid;
grid-template-columns: repeat(2, 1fr);
}
.selector input {
width: 1.2em;
height: 1.2em;
}
.selector label {
font-size: 1.5em;
font-family: sans-serif;
cursor: pointer;
}
.selector input:checked + label {
color: dodgerblue;
}
效果如下图:
最后,为复选框绑定点击事件,当点击复选框时,更新 .inside 元素的背景图片。function init() {
var options = document.getElementsByName('options')
options.forEach((option) => {
option.addEventListener('click', (e) => {
inside.style.backgroundImage = getImageUrl(e.target.value)
})
})
function getImageUrl(opt) {
return 'url(' + opt + '.png' + ')'
}
}
下面是透视神经图的效果:
大功告成!
关于作者
张偶,网络笔名 @comehope,20世纪末触网,被 Web 的无穷魅力所俘获,自此始终战斗在 Web 开发第一线。
《前端每日实战》专栏是我近年来实践项目式学习的笔记,以项目驱动学习,展现从灵感闪现到代码实现的完整过程,亦可作为前端开发的练手习题和开发参考。
拙作《CSS3 艺术》一书已由人民邮电出版社出版,全彩印刷,用100多个生动美观的实例,系统地剖析了 CSS 与视觉效果相关的重要语法,并含有近10小时的视频演示讲解。京东/天猫/当当有售。