Wrote slidably movable end (inertial sliding & rebound) Vue navigation bar assembly ly-tab

This article is reproduced in: Ape 2048 Website ➥ https://www.mk2048.com/blog/blog.php?id=ia21hjjkhj

Some time ago wrote adaptive sliding Vue navigation bar component of a mobile terminal, that has a certain practicality, we may get with (of course, some chiefs themselves better, then there is no need to write it), so two days before finishing her , has been released on GitHub and npm, and point me to npm , point me to the GitHub project , students may need in your project npm install ly-tab -Sor yarn add ly-tabuse specific usage will be mentioned below.

Well, take a look at the effect of it

Well, start nonsense, almost three-month internship, this time along with mentor chiefs have contacted a number of projects, but also learned a lot of things, access to the project are basically mobile terminal project, and with the main frame is Vue. Mobile sure did end or used mobile terminal APP (bah, shit) students will find that a lot of time will have a similar effect on top of this there is a sliding tab navigation bar, I believe we certainly would have seen the Nuggets home.

Realization of ideas

The project was just there this need, so I steal a lazy directly Mint-ui component library of ready-made tabbar and tab-item components, github under the terms of its implementation is found only source to achieve a switching function but can not slide, so, can not steal lazy to have to write their own slightly.

In fact, just the realization tab switching function is not difficult to see the mint-ui use the v-model is actually syntactic sugar, like this

<ly-tab v-model="selected">
    <ly-tab-item></ly-tab-item>
</ly-tab>

Here is the dismantling implement v-model of syntactic sugar

<ly-tab :value="selected" @input="selected = arguments[0]">
    <ly-tab-item></ly-tab-item>
</ly-tab>

And then only need to achieve in the tab-item components when they have been clicked, so that the parent assembly ly-tab component is $emita inputevent, passing a tab-item identifies each unique value as the first argument, on this the only value, mint-ui approach requires the user to manually give each tab-item by props passed a unique id value, as follows Mint uI Demo of implementation:

<mt-tabbar v-model="selected">
    <mt-tab-item id="订单">
        <img slot="icon" src="http://placehold.it/100x100">
        <span slot="label">订单</span>
    </mt-tab-item>
 </mt-tabbar>

However, read the chiefs of thinking when vue among design Tabbar plug after that article that approach would be better, because the parent component <ly-tab/>, as long as know which clicks <ly-tab-item/>on the line ah, then I put every a <ly-tab-item/>component of indexthe index value as its unique identification value is not on line yet.

So the question is: how inside the tab-item components to take their own indexvalue it?

First ly-tab assembly $childrenis an array, since each <ly-tab-item/>component is sequentially created and inserted into the array by way of push, so each <ly-tab-item/>created and push the assembly $childrentime, for the <ly-tab-item/>assembly is (this.$parent.$children.length || 1) - 1not that each <ly-tab-item/>unique component indexvalues of what. In fact, here the click function is switched on already achieved. Paste The following codes are tab-item.vue:

tab-item.vue

<template>
  <a class="ly-tab-item"
       :style="$parent.value === id ? activeStyle : {}"
       @click="$parent.$emit('input', id)">
    <div class="ly-tab-item-icon"><slot name="icon"></slot></div>
    <div class="ly-tab-item-label"><slot></slot></div>
  </a>
</template>

<script>
export default {
  name: 'LyTabItem',
  computed: {
    activeStyle () {
      return {
        color: this.$parent.activeColor,
        borderColor: this.$parent.activeColor,
        borderWidth: this.$parent.lineWidth,
        borderBottomStyle: 'solid'
      }
    }
  },
  data () {
    return {
      id: (this.$parent.$children.length || 1) - 1
    }
  }
}
</script>

<style lang="scss">
.ly-tab-item {
  text-decoration: none;
  text-align: center;
  .ly-tab-item-icon {
    margin: 0 auto 5px;
  }
  .ly-tab-item-label {
    margin: 0 auto 10px;
    line-height: 18px;
  }
}
</style>

Tab.vue on the touch slide, and the general idea inertial sliding springback effect achieved:

  • this.$elMonitor touchstart, touchmove and touchend events;
  • recording the initial position when the touch touchstart startX( event.touches[0].clientX), i.e. the distance from the screen on the left side of the contact;
  • Record the touch position touchmove currentX( event.touches[0].clinetX), then to the touchmove from touchstart or last touchmove to the times touchmove finger movement distance currentX - startX, and then let the content area of translateX += currentX - startXthe content area to follow the movement of the finger, then assign the value currentX as the next startX touchmove initial position calculation;
  • touchmove generated when the viscous resistance when the content exceeds the zone boundary, and the distance to the boundary exceeding The longer viscous resistance,

At this time, the finger moving distance is currentX - startX, the content region needs to move a little distance process, first visual zone width (width of the container) of viewAraeWidththis case is beyond the distance to the boundary outX, the boundary exceeding a predetermined maximum distance of a drag additionalX, then the content each area needs to be moved a distance additionalX * (currentX - startX) / (viewAreaWidth + outX), can be approximated as a mathematical function y=a/(x+b), a, bit is constant, Xa outX, is substantially a function of the image:

That is when outX gradually increased, the content area will be moved from the smaller and smaller, and you'll find more in this direction drag the drag no more.

  • When touchend if the content area beyond the boundaries to let its direct execution rebound (rebound animation process use transition);
  • If not out of bounds, is calculated silenceTime = touchend时的时间戳 - 最后一次touchmove触发的时间戳, for example if silenceTime larger than 100ms, the inertia of the slide is not generated, otherwise there will be a sliding inertia, and therefore requires an initial velocity calculation let go speed = 距离间隔 / 时间间隔, and the time interval calculation interval required from the side of touchmove do some operations, i.e. the need to record each event callback touchmove contact locations and each timestamp when touchmove, and two intermediate variables are stored and the last time stamp contact position, so that by assignment updates, you can get to the separation distance between the last two touchmove and time interval, then the initial velocity can be drawn up.
  • Followed by an inertial sliding process, Reflections: assuming long enough width of the container (i.e. not produce rebound beyond the boundary), then the process should be the inertia of the slide a uniform deceleration until the speed is reduced to 0, the use of uniform deceleration the equation of motion V2=V1-at, V2is zero, then the acceleration acceleration = speed / time, time represents how long this process can be up to you. Then you can use requestAnimationFrame calculated for each frame of animation in the content region to be moved from its asynchronous callback ( vt/2, T take of 16.7 ms), so as to achieve animation by recursively calling inertia slidable on requestAnimationFrame read Zhangxin Xu predecessors CSS3 animations so strong , requestAnimationFrame there with wool? ;
  • Of course, just said is the simplest case, but under normal circumstances, the width of the container is not so long (that is likely to slip beyond the boundaries of inertia), then the whole process should be: first uniform deceleration (not out of bounds), then out of bounds . In the process beyond the boundaries that we want to see is dragging the process out of bounds before with similar animation effects, resistance is growing, increasing the acceleration of movement, we need at each requestAnimationFrame in the process the callback function calculates a new acceleration, where I used a formula for calculating the proportion of their own proposed acceleration *= (reboundExponent + outX) / reboundExponent, then calculate the speed and distance of movement. When the speed is reduced to 0 to stop the recursion, execution rebound animation.

The general idea of the process is such that some specific details see specific code. Interested partners can be small to see on github, point I went to see the github project , you can also clone the code to see local, regional poorly written welcome to correct me, if they feel need it or can help us, then the best , that also wish to point a star, ha ha ......

Ai Aiai, No no, how to start seeking the star, not to say it's the most important - how ly-tab to use it?

How to Use ly-tab

If you want to use the small partners ly-tab, or yarn npm need to download and install in your project:

npm install ly-tab -S

or

yarn add ly-tab

Then the global main.js introduced:

import Vue from 'vue';
import LyTab from 'ly-tab';

Vue.use(LyTab);

Then you can use any of your projects <ly-tab></ly-tab>and <ly-tab-item></ly-tab-item>components without the need to re-introduced

chestnut

<ly-tab v-model="selected" fixBottom>
  <!--  selected是你自己定义的一个在data中用于存放当前tab-item的索引值的变量 -->
  <ly-tab-item v-for="(item, index) in tabList" :key="index">
    {{item.itemName}}
  </ly-tab-item>
</ly-tab>

The above is only chestnuts tabbar implementation, we certainly need to do a project to switch the viewing area, where I briefly about the current practice:

  • Vue-router using the router-view handover done
  • Using the dynamic component (component can be used with asynchronous)

I do it seems to be only used these two, I do not know what other better way, please share ~

Configuration Item

You can give <ly-tab></ly-tab>to customize the effect you want to pass some of the components of configuration items

Configuration Item Types of description Defaults
lineWidth Number fixBottom is false bottom tabbar border-width 1px
activeColor String Font color and border-bottom-color active state red
fixBottom Boolean If (not slides is true) fixed to the bottom view false
additionalX Number The maximum distance approximately equal to the drag out of bounds 50px
reBoundExponent Number Inertial Rebound (The larger the value, the larger the amplitude, the longer the distance inertia rebound) 10
sensitivity Number Sensitivity (the smaller the value, the greater the resistance) of the inertial sliding, can be approximated that deceleration to zero after the hand release time required 1000ms
reBoundingDuration Number Rebound animation duration 360ms

Tips

  • <ly-tab></ly-tab>Content within the package width is the minimum width of the zone <ly-tab></ly-tab>width of the component
  • When <ly-tab></ly-tab>within the assembly area width greater than the content itself before sliding (adaptive)
  • FixBottom If true, the non-slidable

PS:

If the error during installation can first node-sass

npm uninstall node-sass

Uninstall node-sass previously installed, not to prevent it from re-download, install and use Taobao Mirror

npm i node-sass --sass_binary_site=https://npm.taobao.org/mirrors/node-sass/

Of course, you can also directly Global Configuration

npm config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/

After further relates to a node-sass installed is downloaded directly from Taobao mirror source.

Harvest and experience

From the beginning only take into account the realization of functions, in addition to realize the function and try to consider the reusability of components and ease of use, and improve the quality and details of the optimization code and so on, the whole process of the exercise of my thinking ability, but also accumulated experience of my reusable components written in, uh, then ...... also be able to admire their own finished article, ha ha ...... a bad place to write, welcome bigwigs criticism and, finally, still want to ask point star ah ... forget it, go github reward him a star

GitHub: github.com/ScoutYin AuthBy: ScoutYin

Guess you like

Origin www.cnblogs.com/qianduanwriter/p/11786060.html