【问题标题】:Is there a concept of path when a div changes its location?div改变位置时是否有路径的概念?
【发布时间】:2018-01-05 16:56:10
【问题描述】:

下面的代码有一个div,当点击它时,它会在两个容器div之间“移动”

new Vue({
  el: "#container",
  data: {
    left: true
  }
})
#container {
  width: 500px;
  display: flex;
  justify-content: space-between;
}

#left {
  width: 100px;
  background-color: red;
}

#right {
  width: 100px;
  background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.min.js"></script>
<div id="container">
  <div id="left">
    <div id="element" v-if="left" v-on:click="left=!left">element</div>
  </div>
  <div id="right">
    <div id="element" v-if="!left" v-on:click="left=!left">element</div>
  </div>
</div>

当这样一个元素(具有相同的id)在渲染的 DOM 中更改其位置时是否有路径的概念? 如果是这样:有没有办法可视化它从一个位置的过渡到另一个(通过此路径上的幻灯片)?

【问题讨论】:

  • 恐怕你的问题的答案是否定的。您可以淡出和淡入,但如果您想要移动过渡,您需要更改元素的位置属性,而不是重新设置它的父级。
  • 这应该是什么样子?像fiddle 这样可以吗?如果这就是您要查找的内容,我可以添加答案并详细说明我是如何创建它的。但正如 Roy 所提到的,创建一个元素并在点击时更改它的位置可能更容易。就像在这个fiddle 中一样。我认为这看起来更好,因为颜色变化也是动画的。还是这两个元素的内容不同?
  • @AWolf:非常感谢您的提琴 - 他们会做出很好的回答。第二个符合我的要求(我明天会仔细看看)。我想要做的是让两组标签过滤文章列表(一组“显示带有这些标签的文章”,第二组“不显示......”)。过滤和标签切换有效,(我的代码示例是我实际编码的简化)。我只是觉得当点击一个标签时,另一组的幻影太突然了,我宁愿让它从一组滑到另一组——第二小提琴似乎可以实现。

标签: javascript html css vue.js


【解决方案1】:

好的,感谢您更好地向我解释您的用例。现在更清楚您需要什么了。

请查看下面修改后的演示或fiddle

在演示中,我添加了两个滑块和过滤器,因为我已经了解了它应该如何工作。一个“自编码”滑块和一个使用 Vue-js-toggle-button 依赖项。

我认为两者都适合您,但我可能会使用该库,因为它减少了您的代码和样式。

那么它是如何工作的?

我正在使用一个名为animation 的过渡动画,带有transition: all 0.5s ease; 和两个类:

  • left-position 类为绿色背景色,margin-left: 0 使元素位于容器的左侧
  • right-position 带有红色背景的类和 margin-left: calc(75% - 20px); 用于正确的位置。 -20px 是因为我添加了内边距,而 75% 是因为元素的宽度为 25% 以具有将元素推到右边缘的边距。

通过切换include 属性,动画被触发并且边距变化将被动画化。

我在演示中发现的问题

  • 两个滑块可能不同步 - 切换底部滑块会切换两个滑块,但切换另一个不会切换库滑块。不确定,这里有什么问题,只是提一下,如果您只使用一个,那不会有问题。
  • 列表转换有时看起来有点奇怪 - 如果项目因过滤器更改而被删除,它们会出现并逐渐淡出。

注意

演示中的标记输入非常基本,我会为此使用一个库,但因为这不是问题,我认为演示可以。

Vue.use(window['vue-js-toggle-button'].default)

new Vue({
  el: "#container",
/*  components: {
  	toggleButton: window['vue-js-toggle-button']
  },*/
  data: {
    include: true,
    filterTags: 'even odd',
    articles: [{
    	id: 0,
    	title: 'Test0',
      tags: ['even']
    },
    {
    	id: 1,
    	title: 'Test1',
      tags: ['odd']
    },
    {
    	id: 2,
    	title: 'Test2',
      tags: ['even']
    },
    {
    	id: 3,
    	title: 'Test3',
      tags: ['odd']
    },
    {
    	id: 4, // just to test even & odd exluding
    	title: 'Test4',
      tags: ['no number']
    }
    
   ]
  },
  computed: {
  	filtered () {
    	return this.articles.filter((article) => 
      	article.tags.some((tag) => 
        {
          let result = this.filterTags && this.filterTags.indexOf(tag) !== -1
          return this.include ? result: !result;
      	})
      )
    }
  },
  methods: {
  	updateFilterInclude ({value}) {
    	console.log(value)
      this.include = value
    }
  }
})
body {
  font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
}

.vue-js-switch#changed-font {
  font-size: 16px !important;
}

ul {
  list-style-type: none;
}

.flip-list-move {
  transition: transform 0.5s;
}

#container {
  width: 200px;
  /* border: 1px solid black; */
  position: absolute;
  left: 0;
  padding: 5px;
}

.animation {
  -webkit-transition: all 0.5s ease;
  -moz-transition: all 0.5s ease;
  -o-transition: all 0.5s ease;
  -ms-transition: all 0.5s ease;
  transition: all 0.5s ease;
}

.left-position {
  background-color: green;
  /*transform: translate(0, 0);*/
  margin-left: 0;
 }

.right-position {
  background: red;
  /*transform: translate(100%, 0);*/
  margin-left: calc(75% - 20px);
}

input {
  width: calc(100% - 14px);
  padding: 5px;
}

.slider {
  border: 1px solid gray;
  margin-top: 5px;
  padding: 5px;
  border-radius: 10px;
}
.element {
  width: 25%;
  cursor: pointer;
  padding: 10px;
  /* border: 1px solid black; */
  border-radius: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.js"></script>
<script src="https://rawgit.com/euvl/vue-js-toggle-button/master/dist/index.js"></script>
<div id="container">
  Filter tags<input v-model="filterTags"/>
    <div class="slider">
      <div class="element animation" @click="include = !include" :class="{'left-position': include, 'right-position': !include}">
      {{include ? 'include' : 'exlude'}}
      </div>
    </div>
    <hr/>
    <toggle-button
      id="changed-font"
      :width="200"             
      :height="40"
      :color="{checked: 'green', unchecked: 'red'}"
      :labels="{checked: 'include', unchecked: 'exclude'}" :value="include" @change="updateFilterInclude"> {{include ? 'include' : 'exlude'}}</toggle-button>
    <transition-group name="flip-list" tag="ul">
      <li v-for="article in filtered" :key="article">
        {{article.tags.join(' ')}} - {{article.title}}
      </li>
    </transition-group>
</div>

【讨论】:

  • 谢谢 - 我的描述不清楚。屏幕截图在这里:i.imgur.com/WKzR76z.png。箭头是我提到的“路径”(当前单击“你好”会立即将其移动到“不显示...”框 - 我想添加一个幻灯片的概念,以便用户更加了解这一事实它移动了(他可能不会注意到,尤其是有更多标签时)。
  • 好的,我明白了。这似乎有点复杂,因为您必须为您单击的每个标签添加一个过渡。今天晚些时候我会检查这个。但是现在我已经创建了一个基本的小提琴,其中缺少动画。这是fiddle。这是我第一次尝试不修改库,但我认为需要更改 vue-input-tag 代码才能获得预期结果。
【解决方案2】:

一个简单的脚本,动画 div 从起点移动到终点:

move( document.querySelector("#element"),  document.querySelector("#destination") ); 

function move( element, destination){

  var destinationElement= element.cloneNode(true);//https://developer.mozilla.org/fr/docs/Web/API/Node/cloneNode
  
  destinationElement.style.visibility= "hidden";
  destination.appendChild( destinationElement );
  
  animate( element, destinationElement );
  
  
}

//it could be better to use jquery animate: http://api.jquery.com/animate/
function animate( element, destination, step ){
  
  if( !step ) 
    step= 0;
    
  var steps= 100;
  var origin= element.getBoundingClientRect();
  element.style.position= "absolute";
  element.style.top= ( origin.top * ( (steps - step ) / steps ) + 
                     destination.getBoundingClientRect().top * (  step / steps ) ) + "px";
  element.style.left= ( origin.left * ( (steps - step ) / steps ) + 
                     destination.getBoundingClientRect().left * (  step / steps ) ) + "px";

  if( step < steps ){
    setTimeout( function(){
      animate(element, destination, ++step );
    },50);
  }else{
    element.parentNode.removeChild(element);
    destination.style.visibility= "visible";
  }
}
#origin{
  width: 60px;
  height: 150px;
  border: solid 1px red;
}
#destination{
  width: 100px;
  height: 50px;
  position:relative;
  top: -50px;
  left:200px;
  border: solid 1px green;
}

#element{
  
  width: 10px;
  height: 20px;
  border: solid 1px blue;
  background-color: blue;
}
<div id="origin">
  <div id="element">
  </div>
</div>
<div id="destination">
</div>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-03
    • 2014-03-03
    • 1970-01-01
    • 1970-01-01
    • 2017-05-19
    相关资源
    最近更新 更多