CSS / JS:在滑动时更改不透明度

时间:2016-07-13 11:14:32

标签: javascript angularjs css3 ionic-framework css-animations

我想在滑动时更改元素的不透明度。

我想实现类似于片段中的动画,根据我的手指/光标在滑动时拖动元素的程度逐渐应用。

编辑:动画与在Android中清除通知相同

  • 我的第一个想法是处理拖动事件并根据元素的位置和屏幕的宽度更改不透明度。这是一个好的解决方案吗?有没有更好的,也许只有CSS?

我使用离子(我的元素是离子项),所以任何与 ionic / angular1 相关的东西都可能都很好。



table1

div.animated {
    width: 100px;
    height: 100px;
    background: red;
    position: absolute;
    top: 31px;
    animation: right 2s;
    animation-iteration-count: infinite;
    animation-direction: alternate;
    animation-timing-function: linear;
}

.back {
    width: 100px;
    height: 100px;
    border: 1px solid blue;
    position: fixed;
    top: 30px;
    left: 50px;
}

@keyframes right {
    0% {
       left: 0px;
       opacity: 0.1;
    }
    50% { opacity: 1;}
    100% {left: 100px;opacity:0.1}
}




2 个答案:

答案 0 :(得分:2)

非常好的人在谷歌Chrome开发人员进行了一个节目电话SuperCharged这个节目背后的想法是向您展示制作网络应用效果的快捷方法。

他们针对可刷卡进行了一次episode(大概一个小时左右),他们快速做了10分钟episode只是为了给你一个基本的想法。

要回答您的问题,javascript是使其响应的唯一方法,CSS不响应用户输入或操作。

此外,最好在屏幕上移动时使用transform而不是left。他们在演出期间详细解释了原因,但快速的原因是变换可以使用GPU。

无论如何,这里是他们在剧集中制作的代码的现场演示,一目了然,看看它是否是您正在寻找的。无论如何,我建议观看他们的视频,你可以学到很多东西(我当然也是这样)。



/**
 Copyright 2016 Google Inc. All rights reserved.
 Licensed under the Apache License, Version 2.0 (the "License");
 */

'use strict';

class Cards {
  constructor() {
    this.cards = Array.from(document.querySelectorAll('.card'));

    this.onStart = this.onStart.bind(this);
    this.onMove = this.onMove.bind(this);
    this.onEnd = this.onEnd.bind(this);
    this.update = this.update.bind(this);
    this.targetBCR = null;
    this.target = null;
    this.startX = 0;
    this.currentX = 0;
    this.screenX = 0;
    this.targetX = 0;
    this.draggingCard = false;

    this.addEventListeners();

    requestAnimationFrame(this.update);
  }

  addEventListeners() {
    document.addEventListener('touchstart', this.onStart);
    document.addEventListener('touchmove', this.onMove);
    document.addEventListener('touchend', this.onEnd);

    document.addEventListener('mousedown', this.onStart);
    document.addEventListener('mousemove', this.onMove);
    document.addEventListener('mouseup', this.onEnd);
  }

  onStart(evt) {
    if (this.target)
      return;

    if (!evt.target.classList.contains('card'))
      return;

    this.target = evt.target;
    this.targetBCR = this.target.getBoundingClientRect();

    this.startX = evt.pageX || evt.touches[0].pageX;
    this.currentX = this.startX;

    this.draggingCard = true;
    this.target.style.willChange = 'transform';

    evt.preventDefault();
  }

  onMove(evt) {
    if (!this.target)
      return;

    this.currentX = evt.pageX || evt.touches[0].pageX;
  }

  onEnd(evt) {
    if (!this.target)
      return;

    this.targetX = 0;
    let screenX = this.currentX - this.startX;
    if (Math.abs(screenX) > this.targetBCR.width * 0.35) {
      this.targetX = (screenX > 0) ? this.targetBCR.width : -this.targetBCR.width;
    }

    this.draggingCard = false;
  }

  update() {

    requestAnimationFrame(this.update);

    if (!this.target)
      return;

    if (this.draggingCard) {
      this.screenX = this.currentX - this.startX;
    } else {
      this.screenX += (this.targetX - this.screenX) / 4;
    }

    const normalizedDragDistance =
      (Math.abs(this.screenX) / this.targetBCR.width);
    const opacity = 1 - Math.pow(normalizedDragDistance, 3);

    this.target.style.transform = `translateX(${this.screenX}px)`;
    this.target.style.opacity = opacity;

    // User has finished dragging.
    if (this.draggingCard)
      return;

    const isNearlyAtStart = (Math.abs(this.screenX) < 0.1);
    const isNearlyInvisible = (opacity < 0.01);

    // If the card is nearly gone.
    if (isNearlyInvisible) {

      // Bail if there's no target or it's not attached to a parent anymore.
      if (!this.target || !this.target.parentNode)
        return;

      this.target.parentNode.removeChild(this.target);

      const targetIndex = this.cards.indexOf(this.target);
      this.cards.splice(targetIndex, 1);

      // Slide all the other cards.
      this.animateOtherCardsIntoPosition(targetIndex);

    } else if (isNearlyAtStart) {
      this.resetTarget();
    }
  }

  animateOtherCardsIntoPosition(startIndex) {
    // If removed card was the last one, there is nothing to animate. Remove target.
    if (startIndex === this.cards.length) {
      this.resetTarget();
      return;
    }

    const frames = [{
      transform: `translateY(${this.targetBCR.height + 20}px)`
    }, {
      transform: 'none'
    }];
    const options = {
      easing: 'cubic-bezier(0,0,0.31,1)',
      duration: 150
    };
    const onAnimationComplete = () => this.resetTarget();

    for (let i = startIndex; i < this.cards.length; i++) {
      const card = this.cards[i];

      // Move the card down then slide it up.
      card
        .animate(frames, options)
        .addEventListener('finish', onAnimationComplete);
    }
  }

  resetTarget() {
    if (!this.target)
      return;

    this.target.style.willChange = 'initial';
    this.target.style.transform = 'none';
    this.target = null;
  }
}

window.addEventListener('load', () => new Cards());
&#13;
/**
 Copyright 2016 Google Inc. All rights reserved. 
 Licensed under the Apache License, Version 2.0 (the "License");
 */

html,
body {
  margin: 0;
  padding: 0;
  background: #FAFAFA;
  font-family: Arial;
  font-size: 30px;
  color: #333;
}
* {
  box-sizing: border-box;
}
.card-container {
  width: 100%;
  max-width: 450px;
  padding: 16px;
  margin: 0 auto;
}
.card {
  background: #FFF;
  border-radius: 3px;
  box-shadow: 0 3px 4px rgba(0, 0, 0, 0.3);
  margin: 20px 0;
  height: 120px;
  display: flex;
  align-items: center;
  justify-content: space-around;
  cursor: pointer;
}
&#13;
<!-- 
https://github.com/GoogleChrome/ui-element-samples/tree/master/swipeable-cards

https://www.youtube.com/watch?v=rBSY7BOYRo4

/**
 *
 * Copyright 2016 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
-->

<div class="card-container">
  <div class="card">Das Surma</div>
  <div class="card">Aerotwist</div>
  <div class="card">Kinlanimus Maximus</div>
  <div class="card">Addyoooooooooo</div>
  <div class="card">Gaunty McGaunty Gaunt</div>
  <div class="card">Jack Archibungle</div>
  <div class="card">Sam "The Dutts" Dutton</div>
</div>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

Ansrew的非常有用。在Ionic中,使用onDragonRelease指令更容易。

<ion-item on-drag="onDrag($event)" on-release="onRelease($event)" /> 

并使用这些方法设置离子项的样式:

function onDrag (e) {
    var element = e.currentTarget.childNodes[0];
    var screenW = element.offsetWidth;
    var threshold = screenW * 0.16;

    var delta = Math.abs(e.gesture.deltaX);

    if(delta >= threshold) {
        var normalizedDragDistance = (Math.abs(delta) / screenW);
        var opacity = 1 - Math.pow(normalizedDragDistance, 0.7);

        element.style.opacity = opacity;
    } else {
        e.currentTarget.childNodes[0].style.opacity = 1;
    }
}

function onRelease (e) {
    e.currentTarget.childNodes[0].style.opacity = 1;
}