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 >
)
})
}
<canvas width='1080' height='1920' ref={node => this.canvas = node} style={{width: '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
以上是 react 利用react-hammerjs插件实现滑动特效和点击特效 的全部内容, 来源链接: utcz.com/z/381711.html