美文网首页
2019-08-23

2019-08-23

作者: 金桔柠檬加冰 | 来源:发表于2019-08-23 17:32 被阅读0次

    时间轴的实现

    <template>
      <div class="learnPath">
        <div class="part1">
          <div class="htitile">学习路径</div>
          <div class="parent" ref='parent' @mousedown='handleMouseDome' @mousemove='handleMouseMove' @mouseup='handleMouseUp'>
              <div class="timePath" ref='path'>
                <div class="year">2019年</div>
                <!-- 展开前 -->
                <div class="con1" v-if='!openDateList'>
                  <div class="bor"></div>
                  <div class="time">
                    <div class="date" v-for='item in timelist' :key='item.id'>
                      <div class="txt">{{item.date}}</div>
                      <div :class="item.active ? 'active circle' : 'circle'"></div>
                    </div>
                  </div>
                </div>
                <!-- 展开后 -->
                <div class="con2" v-else ref='con2'>
                  <div class="track">
                    <div class="traL"></div>
                    <div class="traC">
                      <ol>
                        <li>
                          <time>
                              05:30
                          </time>
                          <i></i>
                        </li>
                        <li>
                          <time>
                            05:30
                        </time>
                        <i></i>
                        </li> 
                        <li>
                          <time>
                            05:30
                        </time>
                        <i></i>
                        </li>
                        <li>
                          <time>
                            05:30
                        </time>
                        <i></i>
                        </li>
                        <li>
                          <time>
                            05:30
                        </time>
                        <i></i>
                        </li> 
                        <li>
                          <time>
                            05:30
                        </time>
                        <i></i>
                        </li>
                        <li>
                          <time>
                            05:30
                        </time>
                        <i></i>
                        </li>
                        <li>
                          <time>
                            05:30
                        </time>
                        <i></i>
                        </li> 
                        <li>
                          <time>
                            05:30
                        </time>
                        <i></i>
                        </li>
                        <li>
                          <time>
                            05:30
                        </time>
                        <i></i>
                        </li>
                      </ol>
                    </div>
                    <div class="traR">
                      <time>
                        05:30
                      </time>
                    <i class="active"></i>
                    </div>
                  </div>
                  <div class="track">
                    <div class="traL">
                      <time>
                        05:30
                      </time>
                      <i></i>
                    </div>
                    <div class="traC">
                      <ol>
                        <li>
                          <time>
                              05:30
                          </time>
                          <i></i>
                        </li>
                        <li>
                          <time>
                            05:30
                        </time>
                        <i></i>
                        </li> 
                        <li>
                          <time>
                            05:30
                        </time>
                        <i></i>
                        </li>
                        <li>
                          <time>
                            05:30
                        </time>
                        <i></i>
                        </li>
                        <li>
                          <time>
                            05:30
                        </time>
                        <i></i>
                        </li> 
                        <li>
                          <time>
                            05:30
                        </time>
                        <i></i>
                        </li>
                        <li>
                          <time>
                            05:30
                        </time>
                        <i></i>
                        </li>
                        <li>
                          <time>
                            05:30
                        </time>
                        <i></i>
                        </li> 
                        <li>
                          <time>
                            05:30
                        </time>
                        <i></i>
                        </li>
                      </ol>
                    </div>
                    <div class="traR"></div>
                  </div>
                  <!-- <div class="track">
                    <div class="traL"></div>
                    <div class="traC"></div>
                    <div class="traR"></div>
                  </div> -->
                </div>
                <!-- 按钮 -->
                <div class="open" @click='handleOrC'>
                  <i class="el-icon-arrow-up"  v-if='openDateList'></i>
                  <i class="el-icon-arrow-down" v-else></i>
                </div>
                <!-- 放大按钮 -->
                <div class="enlarge" v-if='openDateList'>
                  <div class="percentage">{{maxScale*100 + '%'}}</div>
                  <div class="add" @click='handleAdd'>
                    <i class="el-icon-plus"></i>
                  </div>
                  <div class="reduce" @click='handleReduce'>
                    <i class="el-icon-minus"></i>
                  </div>
                </div>
              </div>
          </div>
        </div>
      </div>
    </template>
    <script>
    import { Icon } from 'element-ui'
    import KnowNew from '@components/myCourse/knowNew'
    import CardTemplate from '@components/myCourse/cardTemplate'
    export default {
      data() {
        return {
          timelist:[
            {
              date: '05.10',
              id: 0,
              active: true
            },
            {
              date: '05.15',
              id: 1,
              active: true
            },
            {
              date: '05.20',
              id: 2,
              active: true
            },
            {
              date: '05.25',
              id: 3,
              active: false
            },
            {
              date: '05.30',
              id: 4,
              active: false
            },
            {
              date: '06.05',
              id: 5,
              active: false
            },
            {
              date: '06.15',
              id: 6,
              active: false
            },
            {
              date: '06.20',
              id: 7,
              active: false
            },
          ],
          openDateList: false,
          boxX: null,
          boxY: null,
          isDrop: false, // 判断能否拖动
          maxScale: 1
        }
      },
      components: {
        KnowNew,
        CardTemplate
      },
      mounted () {
        if (this.openDateList){
          this.setItemPosition()
        }
        window.onmouseup = () => {
          this.isDrop = false
        }
      },
      methods: {
        setItemPosition () {
          const item = this.$refs.con2.children
          const topBor = item[0].children[0]
          let topBorH = getComputedStyle(topBor, null).borderTop
          topBorH = parseInt(topBorH)
          for (let i = 0; i < item.length; i++) {
            const lis = item[i]
            const tops = -i * topBorH
            lis.style.top = tops + 'px'
          }
        },
        // 展开或者关闭时间图
        handleOrC() {
          this.maxScale = 1
          this.openDateList = !this.openDateList;
          this.$refs.path.style.top = 0;
          this.$refs.path.style.left =  0
          this.setAnimation()
        },
        // 放大功能
        handleAdd() {
          if (this.maxScale >= 2) {
            this.maxScale = 2
          } else {
            this.maxScale += 0.5
          }
          this.setAnimation()
        },
        // 缩小功能
        handleReduce() {
          if (this.maxScale <=1 ) {
            this.maxScale = 1
          } else {
            this.maxScale -= 0.5
          }
          if (this.maxScale == 1) {
            this.$refs.path.style.left = 0;
            this.$refs.path.style.top = 0;
          } else if (this.maxScale == 1.5) {
            this.$refs.path.style.right = 0;
            this.$refs.path.style.top = 0;
            this.$refs.path.style.left =  0
          }
          this.setAnimation()
        },
        // 动画过度
        setAnimation() {
          this.$refs.path.style.transform = 'scale('+this.maxScale +')'
          this.$refs.path.style.webkitTransform = 'scale('+this.maxScale +')'
          this.$refs.path.style.msTransform = 'scale('+this.maxScale +')'
          this.$refs.path.style.oTransform = 'scale('+this.maxScale +')'
          this.$refs.path.style.mozTransform = 'scale('+this.maxScale +')'
          this.$refs.path.style.cursor = 'pointer'
          this.$refs.path.style.transition = 'transform 0.3s'
          this.$refs.path.style.webkitTransition = 'transform 0.3s'
          this.$refs.path.style.msTransition = 'transform 0.3s'
          this.$refs.path.style.oTransition = 'transform 0.3s'
          this.$refs.path.style.mozTransition = 'transform 0.3s'
        },
        // 鼠标按下事件
        handleMouseDome(e) {
          let box = this.$refs.path
          var e = e || window.event;//要用event这个对象来获取鼠标的位置
          this.boxX = e.clientX - box.offsetLeft;
          this.boxY = e.clientY - box.offsetTop;
          this.isDrop = true;//设为true表示可以移动
        },
        // 鼠标拖动事件
        handleMouseMove(e) {
          if (this.maxScale == 1) {
            return
          }
          //是否为可移动状态
          if(this.isDrop && this.openDateList) {
            let e = e || window.event
            let moveX = e.clientX - this.boxX;//得到距离左边移动距离
            let moveY = e.clientY - this.boxY;//得到距离上边移动距离
            this.setBor(moveX, moveY)
          }
        },
    
        setBor(x, y) {
          let moveX = x
          let moveY = y
          if(this.maxScale == 2) {
            let wX = this.$refs.parent.offsetWidth / 2
            let hY = this.$refs.parent.offsetHeight / 2
            if(moveX > wX) {
              moveX = wX
            } else if (-wX > moveX ){
              moveX = -wX
            }
            if(moveY > hY ) {
              moveY = hY
            } else if (-hY > moveY) {
              moveY = -hY
            }
          } else if (this.maxScale == 1.5) {
            let wX = this.$refs.parent.offsetWidth / 4
            let hY = this.$refs.parent.offsetHeight / 4
            if(moveX > wX) {
              moveX = wX
            } else if (-wX > moveX ){
              moveX = -wX
            }
            if(moveY > hY ) {
              moveY = hY
            } else if (-hY > moveY) {
              moveY = -hY
            }
          }
          this.$refs.path.style.left = moveX + "px";
          this.$refs.path.style.top = moveY + "px";
        },
    
        // 鼠标弹起
        handleMouseUp() {
          this.isDrop = false
          this.$refs.parent.mousemove = null
          document.onmouseup = () => {
            this.$refs.parent.mousemove = null
          }
        },
    
      },
    }
    </script>
    <style lang='scss' scoped>
      .learnPath{
        width: 100%;
        height: 100%;
        box-sizing: border-box;
        padding: 0px 30px;
        .htitile{
          padding: 32px 0px 19px 0px;
          border-bottom: 1px solid #E6E8E9;
        }
        .parent{
          overflow: hidden;
          position: relative;
          margin-top: 12px;
        }
        .timePath{
          width: 100%;
          /* height: 162px; */
          background-color: #E8F1EC;
          position: relative;
          overflow: hidden;
          .year{
            text-align: center;
            font-size: 20px;
            font-family: SourceHanSansCN-Bold;
            font-weight: bold;
            color: #319F60;
            width: 100%;
            padding: 20px 0;
          }
          .con1{
            width: 100%;
            position: relative;
            /* padding: 42px 0; */
            padding-top: 42px;
            color: #4BBE7C;
            .bor{
              width: 100%;
              height: 2px;
              background: #5BCA8A;
            }
            .time{
              position: absolute;
              /* top: -25px; */
              top: 5px;
              width: 100%;
              display: flex;
              .date{
                    margin: 0px 38px;
                .txt{
                  padding-bottom: 10px;
                }
              }
              .circle{
                width:18px;
                height:18px;
                margin: 0 auto;
                background:#EDF8F2;
                border:2px solid rgba(128, 206, 161, 1);
                box-shadow:0px 4px 8px 0px rgba(75, 128, 199, 0.35);
                border-radius:50%;
              }
            }
          }
          .active{
            background:linear-gradient(-36deg,rgba(79,185,124,1),rgba(107,224,157,1)) !important;
          }
          .con2{
            position: relative;
            margin-top: 45px;
            color: #4BBE7C;
            font-weight:400;
            .track{
              width: 892px;
              /* flex: 1; */
              height: 100px;
              margin: 0 auto;
              padding:0;
              display: flex;
              position: relative;
              &:nth-of-type(1){
                div:nth-of-type(1){
                  display: none !important;
                }
                .traC{
                  width: 90%;
                }
              }
              &:nth-of-type(odd){
                div:first-child{
                  visibility: hidden;
                }
              }
              &:nth-of-type(even){
                div:last-child{
                  visibility: hidden;
                }
              }
              .traL{
                width: 100px;
                height: 100%;
                box-sizing: border-box;
                border: 2px solid #5BCA8A;
                border-radius: 100% 0 0 100%;
                border-right: none;
                line-height: 100px;
                time{
                  display: block;
                  text-align: right;
                  padding-right: 36px;
                }
                i{
                  position: absolute;
                  left: -9px;top: 50%;
                  width: 18px;
                  height: 18px;
                  margin: -9px 0 0 0;
                  box-sizing: border-box;
                  border: 2px solid #80CEA1;
                  background: #fff;
                  border-radius: 50%;
                }
              }
              .traC{
                width: 80%;
                height: 100px;
                border-top: 2px solid #5BCA8A;
                box-sizing: border-box;
                ol{
                  width: 110%;
                  height: 50%;
                  position: relative;
                  top: -50%;
                  display: flex;
                  left: -5%;
                  z-index: 10;
                  li{
                    flex: 1;
                    position: relative;
                    text-align: center;
                    line-height: 50px;
                    time{
                      display: block;
                      font-size: 16px;
                    }
                    i{
                      position: absolute;
                      left: 50%;
                      bottom: -9px;
                      width: 18px;
                      height: 18px;
                      box-sizing: border-box;
                      border: 2px solid #80CEA1;
                      border-radius: 50%;
                      margin: 0 0 0 -9px;
                      background: #fff;
                     
                    }
                  }
                }  
    
    
    
              }
              .traR{
                width: 100px;
                height: 100%;
                border: 2px solid #5BCA8A;
                border-radius: 0 100% 100% 0;
                border-left: none;
                box-sizing: border-box;
                line-height: 100px;
                position: relative;
                time{
                  display: block;
                  text-align: left;
                  padding-left: 36px;
                }
                i{
                  position: absolute;
                  right: -9px;top: 50%;
                  width: 18px;
                  height: 18px;
                  margin: -9px 0 0 0;
                  box-sizing: border-box;
                  border: 2px solid #80CEA1;
                  background: #fff;
                  border-radius: 50%;
                }
              }
            }
          }
          .open{
            width:60px;
            height:16px;
            background:#80CEA1;
            border-radius:10px 10px 0px 0px;
            color: #fff;
            font-weight: bold;
            text-align: center;
            font-size: 18px;
            margin: 30px auto 0;
          }
          .enlarge{
            position: absolute;
            top: 20px;
            right: 15px;
            line-height: 24px;
            text-align: center;
            color: #fff;
            div{
              display: inline-block;
              margin-right: 5px;
            }
            .percentage{
              width:60px;
              height:24px;
              background:#ACD7BE;
              border-radius:12px;
            }
            .add{
              width:24px;
              height:24px;
              background:rgba(24,170,31,1);
              border-radius:2px;
            }
            .reduce{
              width:24px;
              height:24px;
              background:rgba(24,170,31,1);
              border-radius:2px;
            }
          }
        }
      }
    </style>
    
    image.png

    备注:
    该组件主要是实现弧形样式的实现,还有div的放大和缩小动画的实现,以及鼠标按下拖动效果的实现

    相关文章

      网友评论

          本文标题:2019-08-23

          本文链接:https://www.haomeiwen.com/subject/vuwtectx.html