新聞中心
背景
鼠標(biāo)拖拽元素移動,算是一個稍微有點點復(fù)雜的交互。

創(chuàng)新互聯(lián)公司2013年開創(chuàng)至今,先為武漢等服務(wù)建站,武漢等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為武漢企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。
而在本文,我們就將打破常規(guī),向大家介紹一種超強(qiáng)的僅僅使用純 CSS 就能夠?qū)崿F(xiàn)的鼠標(biāo)點擊拖拽效果。
在之前的這篇文章中 -- [1],我們介紹了非常多有意思的純 CSS 的鼠標(biāo)跟隨效果,像是這樣:
但是,可以看到,上面的效果中,元素的移動不是很絲滑。如果你了解上述的實現(xiàn)方式,就會知道它存在比較大的局限性。
本文,我們還是僅僅通過 CSS,來實現(xiàn)一種絲滑的鼠標(biāo)點擊拖動元素移動的效果。
鼠標(biāo)點擊拖拽跟隨效果
OK,什么意思呢?我們先來看一個最最簡單的效果示意圖,實現(xiàn)點擊一個元素,能夠拖動元素進(jìn)行移動的效果:
好的,到這里,在繼續(xù)往下閱讀之前,你可以停一停。這種效果,正常而言,都是必須要借助 JavaScript 才能夠?qū)崿F(xiàn)的。從表現(xiàn)上來看:
- 首先拖拽元素過程,可以任意將元素進(jìn)行移動
- 然后放置元素,讓元素停留在另外一個地方
思考一下,如果不借助 JavaScript 的話,有辦法將元素小球從 A 點移動到 B 點么?這個效果完全就不像是純 CSS 能夠完成的。
答案必然是可以的!整個過程也非常之巧妙,這里我們核心需要利用強(qiáng)大的 resize 屬性。以及,配合通過構(gòu)建一種巧妙的布局,去解決可能會遇到的各種難題。
使用 resize,構(gòu)建可拖拽改變大小的元素
首先,我們利用 resize 屬性來實現(xiàn)一個可改變大小的元素。
什么是 resize 呢?根據(jù) [2]:該 CSS 屬性允許你控制一個元素的可調(diào)整大小性。
其 CSS 語法如下所示:
{
resize: none;
resize: both;
resize: horizontal;
resize: vertical;
resize: block;
resize: inline;
}簡單解釋一下:
- resize: none:元素不能被用戶縮放。
- resize: both:允許用戶在水平和垂直方向上調(diào)整元素的大小。
- resize: horizontal:允許用戶在水平方向上調(diào)整元素的大小。
- resize: vertical:允許用戶在垂直方向上調(diào)整元素的大小。
- resize: block:根據(jù)書寫模式(writing-mode)和方向值(direction),元素顯示允許用戶在塊方向上(block)水平或垂直調(diào)整元素大小的機(jī)制。
- resize: inline:根據(jù)書寫模式(writing-mode)和方向值(direction),元素顯示一種機(jī)制,允許用戶在內(nèi)聯(lián)方向上(inline)水平方向或垂直方向調(diào)整元素的大小。
看一個最簡單的 DEMO:
Lorem ipsum dolor sit amet, consectetur adipisicing elit. A aut qui labore rerum placeat similique hic consequatur tempore doloribus aliquid alias, nobis voluptates. Perferendis, voluptate placeat esse soluta deleniti id!
p {
width: 200px;
height: 200px;
resize: horizontal;
overflow: scroll;
}這里,我們設(shè)置了一個長寬為 200px 的
為橫向可拖拽改變寬度。效果如下:
簡單總結(jié)一些小技巧:
- resize? 的生效,需要配合 overflow: scroll,當(dāng)然,準(zhǔn)確的說法是,overflow 不是 visible,或者可以直接作用于替換元素譬如圖像、
- 我們可以通過resize 的 horizontal、vertical、both 來設(shè)置橫向拖動、縱向拖動、橫向縱向皆可拖動。
- 可以配合容器的max-width、min-width、max-height、min-height 限制可拖拽改變的一個范圍
這里,如果你的對 resize 還有所疑惑,或者想了解更多 resize 的有趣用法,可以看看我的這篇文章:[3]。
將 resize 應(yīng)用到本文實例中
OK,接下來,我們將 resize 實際運用到我們本文的例子中去,首先,我們先簡單實現(xiàn)一個 DIV:
.g-resize {
width: 100px;
height: 100px;
border: 1px solid deeppink;
}如下,非常普通,沒有什么特別的:
但是,通過給這個元素加上 resize: both 以及 overflow: scroll,此時,這個元素的大小就通過元素右下角的 ICON 進(jìn)行拖動改變。
簡單修改下我們的 CSS 代碼:
.g-resize {
width: 100px;
height: 100px;
border: 1px solid deeppink;
resize: both;
overflow: scroll;
}這樣,我們就得到了一個靈活可以拖動的元素:
是的,我們的整個效果,就需要借助這個特性進(jìn)行實現(xiàn)。
在此基礎(chǔ)上,我們可以嘗試將一個元素定位到上面這個可拖動放大縮小的元素的右下角,看著能不能實現(xiàn)上述的效果。
簡單加一點代碼:
.g-resize {
position: relative;
width: 20px;
height: 20px;
resize: both;
overflow: scroll;
}
.g-resize::before {
content: "";
position: absolute;
bottom: 0;
right: 0;
width: 20px;
height: 20px;
border-radius: 50%;
background: deeppink;
}我們利用元素的偽元素實現(xiàn)了一個小球,放置在容器的右下角看看效果:
? ?
如果我們再把整個設(shè)置了 resize: both 的邊框隱藏呢?那么效果就會是這樣:
Wow,整個效果已經(jīng)非常的接近了!只是,認(rèn)真看的話,能夠看到一些瑕疵,就是還是能夠看到設(shè)置了 resize 的元素的這個 ICON:
這個也好解決,在 Chrome 中,我們可以通過另外一個偽元素 ::-webkit-resizer ,設(shè)置這個 ICON 的隱藏。
根據(jù) [4],它屬于整體的滾動條偽類樣式家族中的一員。
其中 ::-webkit-resizer 可以控制出現(xiàn)在某些元素底角的可拖動調(diào)整大小的滑塊的樣式。
所以,這里我就利用這個偽類:
.g-resize {
position: relative;
width: 20px;
height: 20px;
resize: both;
overflow: scroll;
}
.g-resize::before {
content: "";
position: absolute;
bottom: 0;
right: 0;
width: 20px;
height: 20px;
border-radius: 50%;
background: deeppink;
}
.g-resize::-webkit-resizer {
background-color: transparent;
}這樣,這里的核心在于利用了 .g-resize::-webkit-resizer 中的 background-color: transparent,將滑塊的顏色設(shè)置為了透明色。我們就得到了與文章一開始,一模一樣的效果:
解決溢出被裁剪問題
當(dāng)然,這里有個很致命的問題,如果需要移動的內(nèi)容,遠(yuǎn)比設(shè)置了 resize 的容器要大,或者其初始位置不在該容器內(nèi),超出了的部分因為設(shè)置了 overflow: scroll,將無法看到。
因此上述方案存在比較大的缺陷。
舉個例子,假設(shè)我們需要被拖動的元素不再是一個有這樣一個簡單的結(jié)構(gòu):
.g-content {
width: 100px;
height: 100px;
background: black;
pointer-event: none;
&::before {
content: "";
position: absolute;
width: 20px;
height: 20px;
background: yellow;
border-radius: 50%;
}而像是這樣,是一個更為復(fù)雜的布局內(nèi)容展示(當(dāng)然下面展示的也比較簡單,實際中可以想象成任意復(fù)雜結(jié)構(gòu)內(nèi)容):
? ?
如果將這個結(jié)構(gòu),扔到上面的 g-resize 中:
那么就會因為設(shè)置了 overflow: scroll 的原因,將完全看不到,只剩下一小塊:
為了解決這個問題,我們得修改原本的 DOM 結(jié)構(gòu),另辟蹊徑。
方法有很多,譬如可以利用 Grid 布局的一些特性。當(dāng)然,這里我們只需要巧妙的加多一層,就可以完全解決這個問題。
我們來實現(xiàn)這樣一個布局:
解釋一下上述代碼,其中:
- g-container 設(shè)置為絕對定位加上 display: inline-block,這樣其盒子大小就可以由內(nèi)部正常流式布局盒子的大小撐開。
- g-resize 設(shè)置為 position: relative 并且設(shè)置 resize,負(fù)責(zé)提供一個可拖動大小元素,在這個元素的變化過程中,就能動態(tài)改變父容器的高寬。
- g-content 實際內(nèi)容盒子,通過 position: absolute 定位到容器的右下角即可。
看看完整的 CSS 代碼:
.g-container {
position: absolute;
display: inline-block;
}
.g-resize {
content: "";
position: relative;
width: 20px;
height: 20px;
border-radius: 50%;
resize: both;
overflow: scroll;
z-index: 1;
}
.g-content {
position: absolute;
bottom: -80px;
right: -80px;
width: 100px;
height: 100px;
background: black;
pointer-event: none;
&::before {
content: "";
position: absolute;
width: 20px;
height: 20px;
background: yellow;
border-radius: 50%;
transition: .3s;
}
}
.g-container:hover .g-content::before {
transform: scale(1.1);
box-shadow: -2px 2px 4px -4px #333, -4px 4px 8px -4px #333;
}
.g-resize::-webkit-resizer {
background-color: transparent;
}下圖中,你看到的所有元素,都只是 g-content 呈現(xiàn)出來的元素,整個效果就是這樣:
是的,可能你會有所疑惑,下面我用簡單不同顏色,標(biāo)識不同不同的 DOM 結(jié)構(gòu),方便你去理解。
- 紅色邊框表示整個g-container 的大小。
- 用藍(lán)色矩形表示設(shè)置了g-resize 元素的大小。
- 關(guān)掉::-webkit-resizer 的透明設(shè)置,展示出 resize 框的可拖拽 ICON。
.g-container {
border: 3px solid red;
}
.g-resize {
content: "";
background: blue;
resize: both;
overflow: scroll;
}
.g-resize::-webkit-resizer {
// background-color: transparent;
}看看這個圖,整個原理基本就比較清晰的浮現(xiàn)了出來:
完整的原理代碼,你可以戳這里:[5]
實際應(yīng)用
OK,用了比較大篇幅對原理進(jìn)行了描述。下面我們舉一個實際的應(yīng)用場景。使用上述技巧制作的可拖動便簽貼。靈感來自 -- [6]。
代碼也不多,如果你了解了上面的內(nèi)容,下面的代碼將非常好理解:
Lorem ipsum dolor sit amet consectetur?
完整的 CSS 代碼如下:
body {
position: relative;
padding: 10px;
background: url("背景圖");
background-size: cover;
}
.g-container {
position: absolute;
display: inline-block;
}
.g-resize {
content: "";
position: relative;
width: 20px;
height: 20px;
resize: both;
overflow: scroll;
z-index: 1;
}
.g-content {
position: absolute;
bottom: -160px;
right: -180px;
color: rgba(#000, 0.8);
background-image: linear-gradient(
160deg,
rgb(255, 222, 30) 50%,
rgb(255, 250, 80)
);
width: 200px;
height: 180px;
pointer-event: none;
text-align: center;
font-family: "marker felt", "comic sans ms", sans-serif;
font-size: 24px;
line-height: 1.3;
padding: 1em;
box-sizing: border-box;
&:before {
content: "";
position: absolute;
width: 20px;
height: 20px;
top: 0;
left: 0;
border-radius: 50%;
background-image: radial-gradient(
at 60% 30%,
#f99,
red 20%,
rgb(180, 8, 0)
);
background-position: 20% 10%;
cursor: pointer;
pointer-events: none;
transform: scale(0.8);
box-shadow: -5px 10px 3px -8.5px #000, -1px 7px 12px -5px #000;
transition: all 0.3s ease;
transform: scale(0.8);
}
}
.g-container:hover .g-content::before {
transform: scale(0.9);
box-shadow: -5px 10px 6px -8.5px #000, -1px 7px 16px -4px #000;
}
.g-resize::-webkit-resizer {
background-color: transparent;
}我們通過上述的技巧,實現(xiàn)了一個僅僅使用 CSS 實現(xiàn)的自由拖拽的便簽貼。我們可以自由的將其拖拽到任意地方??纯葱Ч?/p>
當(dāng)然,我們可以再配合上另外一個有意思是 HTML 屬性 -- contenteditable。
contenteditable 是一個 HTML TAG 的屬性,表示元素是否可被用戶編輯。如果可以,瀏覽器會修改元素的部件以允許編輯。
簡單修改一下 DOM 結(jié)構(gòu):
Lorem ipsum dolor sit amet consectetur?
此時,元素不僅可以被拖動,甚至可以被重寫,感受一下:
純 CSS 實現(xiàn)的效果,非常的有意思,完整的代碼,你可以戳這里:[7]
最后
基于 resize 這個 CSS 屬性,其實還有很多有意思的用法。譬如我之前使用了 Resize 實現(xiàn)了一個圖片切換預(yù)覽的功能:[8] 可以一并看看,相信能碰撞出更多火花。
感興趣的同學(xué)可以自己動手,更多的去嘗試,組合。
好了,本文到此結(jié)束,希望本文對你有所幫助 ????
參考資料
[1]不可思議的純 CSS 實現(xiàn)鼠標(biāo)跟隨: https://github.com/chokcoco/iCSS/issues/46?。
[2]MDN -- resize: https://developer.mozilla.org/zh-CN/docs/Web/CSS/resize?。
[3]CSS 奇思妙想 | 使用 resize 實現(xiàn)強(qiáng)大的圖片拖拽切換預(yù)覽功能: https://github.com/chokcoco/iCSS/issues/133?。
[4]MDN - ::-webkit-resizer: https://developer.mozilla.org/zh-CN/docs/Web/CSS/::-webkit-scrollbar?。
[5]CodePen Demo -- Pure CSS Auto Drag Demo: https://codepen.io/Chokcoco/pen/PoemNYv?editors=1100?。
[6]scottkellum: https://codepen.io/scottkellum?。
[7]Pure CSS Auto Drag Demo: https://codepen.io/Chokcoco/pen/oNdWxJO?editors=1100?。
[8]CSS 奇思妙想 | 使用 resize 實現(xiàn)強(qiáng)大的圖片拖拽切換預(yù)覽功能: https://juejin.cn/post/6997224854554411045?。
網(wǎng)站題目:僅僅使用純 CSS 鼠標(biāo)點擊拖拽效果
本文路徑:http://m.5511xx.com/article/cdsihoo.html


咨詢
建站咨詢
