自从从事了前端行业, 就得了个职业病, 就是看到任何界面的效果都会思考自己怎么实现, 这不看见 Window10 的日历系统, 就动起了歪心思, 想复现这个效果.
image
效果分析
边框的可见是跟随鼠标位置来改变, 鼠标 hover 的日期显示边框, 鼠标点击过的日期显示边框
实现思路
利用两个盒子的堆叠, 在上面的盒子只显示日期, 下面的盒子有边框, 在鼠标周围区域透明显示下面盒子的信息, 鼠标 hover 和点击简单就不赘述了.
两个盒子堆叠简单, 利用 position 的层级就可以实现, 问题是怎么只让鼠标周围的区域透明显示, 这里我想到了一个陈迹多年的 CSS 属性 clip,clip 是老式的剪切属性, 必须要 absolute 或者 fixed 定位的元素才能使用, 并且只能剪裁正方形, 他有个升级版 clip-path 对元素的定位没有要求, 而且也可以剪裁更多的形状, 可以剪切圆形, 他剪切后的标签会显示底层的内容, 这个属性放置在上层盒子上, 监听鼠标位置动态设置 clip-path 的位置即可.
代码
- <template>
- <div class="mag">
- <div class="magBox clearfix" :style="`-webkit-clip-path: circle(25% at ${mouseX}px ${mouseY}px);`">
- <div v-for="(item, index) in data" :key="index"></div>
- </div>
- <div class="magBox shadowBox clearfix" @mousemove='touchmoveFn'>
- <div v-for="(item, index) in data" :key="item" @click='activeNum = index' :class="{'isActive': index == activeNum}">{{item}}</div>
- </div>
- </div>
- </template>
- <script>
- export default {
- data () {
- return {
- mouseX: 0,
- mouseY: 0,
- data: [],
- isActive: [],
- activeNum: null,
- boxX: 0,
- boxY: 0,
- boxWidth: 0,
- boxHeight: 0,
- }
- },
- mounted() {
- // 1. 获取盒子对应页面上的位置和宽高
- let box = document.querySelector('.magBox')
- this.boxX = box.offsetLeft
- this.boxY = box.offsetTop
- // 需要待到盒子已经生成后获取宽高要不获取的高度不对
- this.$nextTick(() => {
- this.boxWidth = box.offsetWidth
- this.boxHeight = box.offsetHeight
- })
- // 2. 遍历设置日期
- for (let index = 0; index <30; index++) {
- this.data.push(index + 1)
- this.isActive.push(false)
- }
- },
- methods: {
- // 3. 鼠标移动的方法
- touchmoveFn(e) {
- // 当前鼠标位置减去盒子位置即可 由于我们盒子有 translate(-50%, -50%) 的问题 需要再加上盒子宽高的一半才是正确的鼠标相对于盒子的位置
- this.mouseX = e.pageX - this.boxX + this.boxWidth / 2
- this.mouseY = e.pageY - this.boxY + this.boxHeight / 2
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .mag {
- position: relative;
- width: 100vw;
- height: 100vh;
- }
- .magBox {
- position: absolute;
- left: 50%;
- top: 50%;
- transform: translate(-50%, -50%);
- width: 364px !important;
- padding-bottom: 4px;
- z-index: 1;
- div {
- float: left;
- width: 50px;
- height: 50px;
- text-align: center;
- box-sizing: border-box;
- margin: 2px 0 0 2px;
- line-height: 46px;
- border: 2px solid rgba(200, 200, 200, 0.5)
- }
- }
- .shadowBox {
- div {
- border: none;
- line-height: 50px;
- }
- div:hover {
- line-height: 46px;
- border: 2px solid rgba(6, 63, 250, 0.3)
- }
- .isActive {
- line-height: 46px;
- border: 2px solid rgba(6, 63, 250, 0.6)
- }
- }
- </style>
来源: http://www.jianshu.com/p/b2c2584cdccf