zoukankan      html  css  js  c++  java
  • react 利用react-hammerjs插件实现滑动特效和点击特效

    react-hammerjs是一款由hammer.js的JS插件来实现在react中实现手势滑动的事件插件,

    它有各种各样的手势支持效果,这里我们就使用下它最简单的3种效果来实现我们要的动画

    分别是点击(onTap)、滑动(onPan)、滑动结束(onPanEnd)

    具体事件参数和其它事件可以参考官网

    动画效果

    上代码

    import React from 'react'
    import {draw} from './canvas'
    import Hammer from 'react-hammerjs'
    import axios from './../axios'
    import "./index.css"
    
    
    export default class Index extends React.Component{
        state = {
            bubble:[],
            bubbleState:true,
            bubbleClass:[
                {
                    class:'bubble-1',
                },
                {
                    class:'bubble-2',
                },
                {
                    class:'bubble-3',
                },
                {
                    class:'bubble-4',
                },
                {
                    class:'bubble-5',
                }
            ],
            fishList:[],
            param:[
                {
                    version:'v1',
                    cityid:'101020100'
                }
            ]
        }
        componentWillMount() {
            this.tem()
            let num = Math.floor(Math.random()*5);
            console.log("num----->",num)
        }
        tem=()=>{ //天气温度
            axios.get("api/",this.state.param,
                result=> {
                    console.log("--------->",result)
                    this.setState({listData:result.data ||[]})
                },
                result=> {
    
                }
            );
        }
        handleClick=(e)=>{ //点击
            let fishList = this.state.fishList;
            let leftX = e.center.y
            let topY = e.center.y
            let fish = {}
    
            if(1080/2>e.center.x){ //左
                console.log("点击-1-》",e,topY,1080/2>e.center.x);
                fish.left = '-30'
                fish.right = ''
                fish.top = topY
                fish.class='fishClassL-1'
                fish.src='./video/fish-1.jpg'
            }else { //右
                fish.left = ''
                fish.right = '-30'
                fish.top = topY
                fish.class='fishClassR-1'
                fish.src='./video/fish-2.jpg'
                console.log("点击-2-》",e,topY,1080/2>e.center.x);
            }
    
            console.log("fish----->",fish)
            fishList.push(fish)
            this.setState({  
                fishList:fishList
            })
        }
        onPan=(e)=>{ //划动
            let bubbleState = this.state.bubbleState
            if(bubbleState){
                let num = Math.floor(Math.random()*5);
                let bubbleClass = this.state.bubbleClass
                let bubble = {}
                bubble.left = e.center.x
                bubble.top = e.center.y
                bubble.src = './video/bubble-1.png'
                bubble.class = bubbleClass[num].class
                // bubble.class = 'bubble-3'
                let bubbleList = this.state.bubble
                bubbleList.push(bubble)
                // console.log("划动--》",e);
    
                this.setState({
                    bubble:bubbleList,
                    // bubbleState:false
                })
            }
        }
        onPanEnd =()=>{
            this.setState({
                bubbleState:false
            })
            console.log("划动结束--》");
            setTimeout(()=> {
                this.setState({
                    bubble:[],
                    bubbleState:true
                })
            },3000)
        }
        componentDidMount() {
            if (this.canvas) {
                draw(this.canvas)
            }
        }
        render() {
            const { percent,tops } = this.state;
            return(
                <Hammer onTap={this.handleClick}  onPan={this.onPan} onPanEnd={this.onPanEnd} >
                    <div id={'scrollBox'} className="video-box">
                        {/*<div className="fish" style={{left:`${percent}%`,top:`${tops}px`}}></div>*/}
                        {
                            this.state.bubble && this.state.bubble.map((item,index)=>{
                                return (
                                    <div className="bubble-box" key={index} style={{left:`${item.left}px`,top:`${item.top}px`}}><img className={`${item.class}`} src={item.src} /></div>
                                )
                            })
                        }
                        {
                            this.state.fishList && this.state.fishList.map((item,index)=>{
                                return (
                                    <div id="fish-box" className={`${item.class}`} key={index} style={{left:`${item.left}px`,right:`${item.right}px`,top:`${item.top}px`}}><img  src={item.src} /></div>
                                )
                            })
                        }
                        <canvas width='1080' height='1920'  ref={node => this.canvas = node}  style={{ '100%',height: 'auto',}}></canvas>
                    </div>
                </Hammer>
            )
        }
    }
    .video-box{
        /*background-color: #0BB20C;*/
        height: auto;
        width: 100%;
        position: relative;
    }
    .bubble-box{
        position: absolute;
    }
    .bubble-box img{
    
    }
    .bubble-box img.bubble-1{
        width: 20px;
        height: 20px;
        animation:mymove1 5s normal;
    }
    .bubble-box img.bubble-2{
        width: 10px;
        height: 10px;
        animation:mymove2 4s normal;
    }
    .bubble-box img.bubble-3{
        width: 15px;
        height: 15px;
        animation:mymove3 5s normal;
    }
    .bubble-box img.bubble-4{
        width: 18px;
        height: 18px;
        animation:mymove4 4s normal;
    }
    .bubble-box img.bubble-5{
        width: 12px;
        height: 12px;
        animation:mymove5 5s normal;
    }
    .fish{
        position: absolute;
        /*left: 0;*/
        width: 20px;
        height: 20px;
        background-color: #0CD0C0;
    }
    
    
    @keyframes mymove1
    {
        0% {
            opacity: 1;
            transform:translateY(0px);
        }
        100% {
            opacity: 0;
            transform:translateY(-55px);
        }
    }
    @keyframes mymove2
    {
        0% {
            opacity: 1;
            transform:translateY(0px);
        }
        100% {
            opacity: 0;
            transform:translateY(-65px);
        }
    }
    @keyframes mymove3
    {
        0% {
            opacity: 1;
            transform:translateY(0px);
        }
        100% {
            opacity: 0;
            transform:translateY(-75px);
        }
    }
    @keyframes mymove4
    {
        0% {
            opacity: 1;
            transform:translateY(0px);
        }
        100% {
            opacity: 0;
            transform:translateY(-95px);
        }
    }
    @keyframes mymove5
    {
        0% {
            opacity: 1;
            transform:translateY(0px);
        }
        100% {
            opacity: 0;
            transform:translateY(-85px);
        }
    }
    
    
    
    
    #fish-box{
        position: absolute;
    
    }
    #fish-box img{
        width: 30px;
        height: 30px;
    }
    
    .fishClassL-1{
        animation:fishmovel1 10s normal;
    }
    @keyframes fishmovel1
    {
        0% {
            left: -30px;
        }
        100% {
            left: 1100px;
        }
    }
    .fishClassR-1{
        animation:fishmover1 10s normal;
    }
    @keyframes fishmover1
    {
        0% {
            right: -30px;
        }
        100% {
            right: 1100px;
        }
    }
    /*1920*1080*/

    利用canvas将视频渲染成动画背景

    export const draw = (canvas) => {
        if (canvas) {
            //获取canvas上下文
            let ctx = canvas.getContext('2d');
            let videoState = true;
            //创建video标签,并且设置相关属性
            let video = document.createElement('video');
    
            let videoSrc1 = './video/video-2.mp4'
            let videoSrc2 = './video/video-3.mp4'
            video.preload = true;
            video.autoplay = true;
            video.loop = true;
            video.src = videoSrc1;
            // video.className = 'aaaaaaaaa'
            //document.body.appendChild(video);
    
            //监听video的play事件,一旦开始,就把video逐帧绘制到canvas上
            video.addEventListener('play',() => {
                let play = () => {
                    ctx.drawImage(video,0,0);
                    requestAnimationFrame(play);
                };
                play();
            },false)
    
            //暂停/播放视频
            canvas.addEventListener('click',() => {
                // if (!video.paused) {
                //     video.pause();
                //     console.log("暂停视频!")
                // } else {
                //     video.play();
                //     console.log("开始视频!")
                // }
                if (videoState) {
                    // video.src = videoSrc2;
                    // videoState = false;
                    // canvasBg = canvas
    
                } else {
                    // video.src = videoSrc1;
                    // videoState = true;
                }
            },false);
    
    
    
        }
    }
    View Code

    封装axios插件

    // import JsonP from 'jsonp'
    import axios from 'axios'
    // import showMsg from '../components/notification'
    
    // 配置API接口地址
    var root = 'https://www.tianqiapi.com/'
    // var root = '/prefix'
    // 自定义判断元素类型JS
    function toType (obj) {
        return ({}).toString.call(obj).match(/s([a-zA-Z]+)/)[1].toLowerCase()
    }
    // 参数过滤函数
    function filterNull (o) {
        for (var key in o) {
            if (o[key] === null) {
                delete o[key]
            }
            if (toType(o[key]) === 'string') {
                o[key] = o[key].trim()
            } else if (toType(o[key]) === 'object') {
                o[key] = filterNull(o[key])
            } else if (toType(o[key]) === 'array') {
                o[key] = filterNull(o[key])
            }
        }
        return o
    }
    /*
      接口处理函数
      这个函数每个项目都是不一样的,我现在调整的是适用于
      https://cnodejs.org/api/v1 的接口,如果是其他接口
      需要根据接口的参数进行调整。参考说明文档地址:
      https://cnodejs.org/topic/5378720ed6e2d16149fa16bd
      主要是,不同的接口的成功标识和失败提示是不一致的。
      另外,不同的项目的处理方法也是不一致的,这里出错就是简单的alert
    */
    
    function apiAxios (method, url, params, success, failure) {
        if (params) {
            params = filterNull(params)
        }
        axios({
            method: method,
            url: url,
            data: method === 'POST' || method === 'PUT' ? params : null,
            params: method === 'GET' || method === 'DELETE' ? params : null,
            baseURL: root,
            withCredentials: false
        }).then(function (res) {
            // if (res.data.success === true) {
            //   if (success) {
            //     success(res.data)
            //   }
            // } else {
            //   if (failure) {
            //     failure(res.data)
            //   } else {
            //     // window.alert('error: ' + JSON.stringify(res.data))
            //     console.log('error: 222' + JSON.stringify(res.data));
            //   }
            // }
            success(res.data);
            // success(JSON.stringify(res.data));
        }).catch(function (err) {
            // let res = err.response
            // if (err) {
            //   // window.alert('api error, HTTP CODE: ' + res.status)
              console.log('api error333, HTTP CODE: ' + err.status);
            // }
    
            // showMsg.error('api error, HTTP CODE: ' +err.status);
        })
    }
    
    // 返回在react模板中的调用接口
    export default {
        get: function (url, params, success, failure) {
            return apiAxios('GET', url, params, success, failure)
        },
        post: function (url, params, success, failure) {
            return apiAxios('POST', url, params, success, failure)
        },
        put: function (url, params, success, failure) {
            return apiAxios('PUT', url, params, success, failure)
        },
        delete: function (url, params, success, failure) {
            return apiAxios('DELETE', url, params, success, failure)
        }
    }
    View Code
  • 相关阅读:
    2017.10.12
    2017.10.25
    2017.10.24
    进度条06
    课堂练习(返回一个环状一维整数数组中最大子数组的和)
    团队项目成员和题目
    团队作业--四则运算网页版
    进度条04
    个人作业(最大子数组)
    进度条03
  • 原文地址:https://www.cnblogs.com/zhixi/p/10718581.html
Copyright © 2011-2022 走看看