Toggle navigation
在线编辑器
在线代码
文本比较
jQuery下载
前端库
在线手册
登录/注册
下载代码
html
css
js
分享到微信朋友圈
X
html
Marc
horse
speak
woman
I
American
An
css
@import url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;700&display=swap"); html { display: -webkit-box; display: flex; color: #fff; font-family: "Open Sans", sans-serif; min-height: 100vh; width: 100vw; font-size: 16px; box-sizing: border-box; } html * { box-sizing: inherit; } body { display: -webkit-box; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; flex-direction: column; -webkit-box-flex: 0; flex: 0 0 100%; margin: 0; padding: 3rem 1rem; background: #122023; -webkit-box-align: center; align-items: center; -webkit-box-pack: start; justify-content: flex-start; } .words { display: -webkit-box; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; flex-direction: column; padding: 2rem; border: 1px solid #596265; border-radius: 1rem; width: 350px; max-width: 100%; } .destination { display: -webkit-box; display: flex; -webkit-box-orient: horizontal; -webkit-box-direction: normal; flex-flow: row wrap; -webkit-box-align: start; align-items: flex-start; align-content: flex-start; margin: 0 0 4rem; min-height: 100px; background: repeating-linear-gradient(to bottom, transparent 0, transparent 44px, #263032 44px, #263032 45px, transparent 45px, transparent 48px); } .destination .word { margin: 0 0.125rem 0.5rem; } .origin { display: -webkit-box; display: flex; -webkit-box-orient: horizontal; -webkit-box-direction: normal; flex-flow: row wrap; -webkit-box-pack: center; justify-content: center; -webkit-box-align: start; align-items: flex-start; max-width: 275px; margin: 0 auto; } .container { display: -webkit-box; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; flex-direction: column; -webkit-box-pack: start; justify-content: flex-start; margin: 0 0.125rem 0.25rem; border-radius: 0.5rem; background: #596265; box-sizing: content-box; padding-bottom: 0.125rem; -webkit-transition: 0.25s ease; transition: 0.25s ease; } .container:empty { background: #263032; } .word { box-sizing: border-box; background: #122023; border: 1px solid #596265; padding: 0.5rem; border-radius: 0.5rem; cursor: pointer; font-weight: 700; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .word:active { -webkit-transition: 0.25s ease; transition: 0.25s ease; -webkit-transform: scale(1.05, 1.05) translateY(-0.25rem); transform: scale(1.05, 1.05) translateY(-0.25rem); }
JavaScript
const destination = document.querySelector(".destination"); // container where selected words go const origin = document.querySelector(".origin"); // container where words initially start const words = origin.querySelectorAll(".word"); // nodeList of all the words in the origin let isAnimating = false; // bool to prevent competing animations (clicking a word before the previous word has finished moving) // FLIP technique animation (First Last Invert Play) const flip = (word, settings) => { // calculate the difference in position between where the word started and where it ended (First - Last = Invert) const invert = { x: settings.first.left - settings.last.left, y: settings.first.top - settings.last.top }; // do the animation (Play) from the original (Invert) position to the final current position let animation = word.animate( [ { transform: `scale(1,1) translate(${invert.x}px, ${invert.y}px)` }, { transform: `scale(1,1) translate(0, 0)` } ], { duration: 300, easing: "ease" } ); // signify that animation has completed animation.onfinish = () => (isAnimating = false); }; // move the word from the origin to the destination const move = (word) => { const id = Math.random(); // random number used to link the word to its container (used in the putback function) const container = word.closest(".container"); // the selected word's container element let rect = word.getBoundingClientRect(); // selected word's DOM rect let first, last; // containers for the initial and final (First and Last) positions of the element isAnimating = true; //signify an animation has started (or is about to) // give both the container and the word a data-id (used in the putback function) (using data-id and not a var because you can query for a data-attribute) container.dataset.id = id; word.dataset.id = id; // set the container to the heighth width of the word (so it stays visible when empty) container.style.height = `${word.offsetHeight}px`; container.style.width = `${word.offsetWidth}px`; // assign the initial top/left px values of the word -> move the word to the destination -> recaculate the the word's DOM rect in new position -> assign the final top/left values first = { top: rect.top, left: rect.left }; destination.insertAdjacentElement("beforeend", word); rect = word.getBoundingClientRect(); last = { top: rect.top, left: rect.left }; // send word, and its caculated vales to the flip funciton flip(word, { first, last }); }; const putback = (word) => { const id = word.dataset.id; // get the ID of the current word const container = origin.querySelector(`[data-id="${id}"]`); // query for the container w/ the matching ID const siblings = [...destination.querySelectorAll(".word")].filter( (sib) => sib !== word ); // find the other word elements in the destination so we can animate them when the selected word is put back let rect = word.getBoundingClientRect(); // selected word's DOM rect let first, last; // containers for the initial and final (First and Last) positions of the element isAnimating = true; //signify an animation has started (or is about to) first = { top: rect.top, left: rect.left }; // assign the initial top/left px values // get the initial top/left px values for each sibling siblings.forEach((sib) => { let rect = sib.getBoundingClientRect(); // I am assigning this value as a property of the element object because trying to keep a // variable linked to this element inside a loop that we can use later in a different loop // would be a real big pain. Best practice is not to modify objects/classes you don't own, // so to be safe and avoid overwriting an existing property value (ele.first or ele.last) // I am prefixing the property name with __ sib.__first = { top: rect.top, left: rect.left }; }); container.insertAdjacentElement("beforeend", word); //move the word from the destination back to its original container rect = word.getBoundingClientRect(); // selected word's new DOM rect last = { top: rect.top, left: rect.left }; // assign the final top/left px values // get the final top/left px values for each sibling siblings.forEach((sib) => { let rect = sib.getBoundingClientRect(); sib.__last = { top: rect.top, left: rect.left }; }); flip(word, { first, last }); // animate the word siblings.forEach((sib) => flip(sib, { first: sib.__first, last: sib.__last })); // animate the siblings // clean up the junk we added during the move function() container.style.height = ""; container.style.width = ""; container.removeAttribute("data-id"); word.removeAttribute("data-id"); }; // add a conditional eventListener to each word words.forEach((word) => { const event = () => { if (isAnimating) return; // if we already have an animation playing, don't let the user start a new one word.closest(".container") ? move(word) : putback(word); // decide if we should use the move() or putback() functions based on the word's current location }; word.addEventListener("mouseup", event); word.addEventListener("touchend", event); });
粒子
时间
文字
hover
canvas
3d
游戏
音乐
火焰
水波
轮播图
鼠标跟随
动画
css
加载动画
导航
菜单
按钮
滑块
tab
弹出层
统计图
svg
×
Close
在线代码下载提示
开通在线代码永久免费下载,需支付20jQ币
开通后,在线代码模块中所有代码可终身免费下!
您已开通在线代码永久免费下载,关闭提示框后,点下载代码可直接下载!
您已经开通过在线代码永久免费下载
对不起,您的jQ币不足!可通过发布资源 或
直接充值获取jQ币
取消
开通下载
<!doctype html> <html> <head> <meta charset="utf-8"> <title>交互式选择-jq22.com</title> <script src="https://www.jq22.com/jquery/jquery-1.10.2.js"></script> <style>
</style> </head> <body>
<script>
</script>
</body> </html>
2012-2021 jQuery插件库版权所有
jquery插件
|
jq22工具库
|
网页技术
|
广告合作
|
在线反馈
|
版权声明
沪ICP备13043785号-1
浙公网安备 33041102000314号