javascript - CSS/JS 模糊,除了鼠标周围
问题描述
我正在尝试从头开始开发一个网站。我正在使用 html、css 和 js(在需要时使用 jQuery 和其他 js 库)。我想拥有可以在任何地方删除而无需安装额外插件/脚本的代码。所有需要的东西都应该放在一个文件夹中,我可以放置在任何地方并运行(即插即用风格),所以我下载了所有库(只有引导程序、jQuery 和 Vague.js atm)。
在其中一个页面中,我有多个图像以类似旋转木马的方式移动。图片覆盖了页面,是页面上唯一的东西(除了徽标和菜单按钮)。我需要做的是使屏幕/图像模糊,只有光标周围的圆圈可见。目前,我设法模糊了所有图像,并在鼠标悬停在它们上方时让它们聚焦,但我不知道如何只聚焦图像的一小部分。
我知道这不是处理事情的理想方式,但为了让轮播顺利运行并在多个页面中可复制,我必须复制所有图像并进行 css 转换操作,关键帧移动 -50%。我知道这部分可能会更好,你可以忽略。我目前拥有的是:
<div class="scrollWrapper">
<div id="scroll" class="imgScroll" onclick="toggleAnimation();">
<img class="scrollingImage" src="image1.jpg" alt="Window showcase image">
<img class="scrollingImage" src="image2.jpg" alt="Window showcase image">
<img class="scrollingImage" src="image3.jpg" alt="Window showcase image">
<img class="scrollingImage" src="image4.jpg" alt="Window showcase image">
<img class="scrollingImage" src="image5.jpg" alt="Window showcase image">
<img class="scrollingImage" src="image1.jpg" alt="Window showcase image">
<img class="scrollingImage" src="image2.jpg" alt="Window showcase image">
<img class="scrollingImage" src="image3.jpg" alt="Window showcase image">
<img class="scrollingImage" src="image4.jpg" alt="Window showcase image">
<img class="scrollingImage" src="image5.jpg" alt="Window showcase image">
</div>
</div>
.scrollWrapper{
overflow: hidden;
}
.imgScroll{
background-color: dimgrey;
width: max-content;
font-size: 0;
z-index: -999;
height: 100vh;
}
.scrollingImage{
filter: blur(10px);
-webkit-filter: blur(10px);
display: inline-block;
height: 100%;
}
.scrollingImage:hover{
filter: blur(0px);
-webkit-filter: blur(0px);
}
@keyframes scrolling{
0% {transform: translateX(0%);}
100% {transform: translateX(-50%);}
}
.imgScroll{
animation: scrolling 60s linear infinite;
z-index: -1000;
}
body .scrollWrapper .pause{
animation-play-state: paused;
-webkit-animation-play-state: paused;
-moz-animation-play-state:paused;
-o-animation-play-state:paused;
}
function toggleAnimation() {
scroll = document.getElementById('scroll');
if(scroll.classList.contains('pause')){
scroll.classList.remove('pause');
}else{
scroll.classList.add('pause');
}
}
我目前的想法是用类 scrollWrapper 模糊 div 并以某种方式在光标周围有一个区域被聚焦,但我不知道该怎么做。
我环顾四周,发现了这篇文章,但据我所知,这些解决方案适用于单个静态图像,而不适用于多个移动图像。我现在在搞乱 Vague.js,但不知道该怎么做。
我不是网络开发人员,并且很少使用 js/jquery,所以我开始因为无法弄清楚这一点而感到愚蠢......这是我在改变完全不同的东西之前的最后手段,所以任何帮助都会不胜感激。
解决方案
用新的CSS做到这backdrop-filter
一点很容易,最难的部分是在过滤器上设置一个洞。
幸运的是,我们有 stackoverflow。
对于一个圆,最简单的可能是使用径向梯度作为 a mask-image
,如this answer所示。
const blur_elem = document.getElementById( "blur-around" );
document.onmousemove = (evt) => {
blur_elem.style.transform = `translate(${evt.clientX}px, ${evt.clientY}px)`;
};
#blur-around {
position: fixed;
z-index: 999;
pointer-events: none;
/* twice the viewport size so it always covers fully */
width: 200vw;
height: 200vh;
/* negative offset by half so we are sure we cover the full viewport */
left: -100vw;
top: -100vh;
/* we'll use transform translate to move it */
transform-origin: center;
-webkit-backdrop-filter: blur(15px);
backdrop-filter: blur(15px);
-webkit-mask-image: radial-gradient(50px at 50% 50%, transparent 100%, black 100%);
mask-image: radial-gradient(50px at 50% 50% , transparent 100%, black 100%)
}
/* falback for browsers that don't have backdrop-filter */
@supports not ((backdrop-filter: blur(0px)) or (-webkit-backdrop-filter: blur(0px))) {
#blur-around {
background-color: rgba(255,255,255,.8);
}
}
<div id="blur-around"></div>
<p>Works over any content</p>
<img src="https://picsum.photos/250/250">
<img src="https://picsum.photos/360/200">
不幸的是,Safari 并不完全支持该mask-image
属性,所以我们可能需要其他东西。
我们还可以使用clip-path
带有偶数路径的 CSS,如该答案所示。
不幸的是,Chrome 仍然不支持path()
for 的功能clip-path
,所以我们必须创造性地使用该polygon()
功能并定义每个点的顶点。
尽管如此,对于一个矩形形状,它所需要的只是首先绘制与元素大小相同的外部矩形,然后在任何我们想要的地方绘制内部矩形,同时确保我们始终关闭这两个形状。
const blur_elem = document.getElementById( "blur-around" );
document.onmousemove = (evt) => {
blur_elem.style.transform = `translate(${evt.clientX}px, ${evt.clientY}px)`;
};
#blur-around {
position: fixed;
z-index: 999;
pointer-events: none;
/* twice the viewport size so it always covers fully */
width: 200vw;
height: 200vh;
/* negative offset by half so we are sure we cover the full viewport */
left: -100vw;
top: -100vh;
/* we'll use transform translate to move it */
transform-origin: center;
-webkit-backdrop-filter: blur(15px);
backdrop-filter: blur(15px);
--rect-size: 100px;
clip-path: polygon( evenodd,
/* outer rect */
0 0, /* top - left */
100% 0, /* top - right */
100% 100%, /* bottom - right */
0% 100%, /* bottom - left */
0 0, /* and top - left again */
/* do the same with inner rect */
calc(50% - var(--rect-size) / 2) calc(50% - var(--rect-size) / 2),
calc(50% + var(--rect-size) / 2) calc(50% - var(--rect-size) / 2),
calc(50% + var(--rect-size) / 2) calc(50% + var(--rect-size) / 2),
calc(50% - var(--rect-size) / 2) calc(50% + var(--rect-size) / 2),
calc(50% - var(--rect-size) / 2) calc(50% - var(--rect-size) / 2)
);
}
/* falback for browsers that don't have backdrop-filter */
@supports not ((backdrop-filter: blur(0px)) or (-webkit-backdrop-filter: blur(0px))) {
#blur-around {
background-color: rgba(255,255,255,.8);
}
}
<div id="blur-around"></div>
<p>Works over any content</p>
<img src="https://picsum.photos/250/250">
<img src="https://picsum.photos/360/200">
虽然用一个圆圈来制作它(正如评论中所要求的那样)开始变得有点不那么可读了,虽然它也可以在 CSS 中硬编码,但它会成为一个很大的规则,我更喜欢直接留下一个 javascript 生成器这个答案:
function makeCircleHoleClipPathRule( radius ) {
const inner_path = [];
const circumference = Math.PI * radius;
const step = Math.PI * 2 / circumference;
// we are coming from top-left corner
const start_step = circumference * (5 / 8);
for( let i = start_step; i < circumference + start_step; i++ ) {
const angle = step * i;
const x = radius * Math.cos( angle );
const y = radius * Math.sin( angle );
const str = `calc( 50% + ${ x }px ) calc( 50% + ${ y }px )`;
inner_path.push( str );
}
// avoid rounding issues
inner_path.push( inner_path[ 0 ] );
return `polygon( evenodd,
/* outer rect */
0 0, /* top - left */
100% 0, /* top - right */
100% 100%, /* bottom - right */
0% 100%, /* bottom - left */
0 0, /* and top - left again */
${ inner_path.join( "," ) }
)`;
}
const blur_elem = document.getElementById( "blur-around" );
// set the clip-path rule
blur_elem.style.clipPath = makeCircleHoleClipPathRule( 50 );
document.onmousemove = (evt) => {
blur_elem.style.transform = `translate(${evt.clientX}px, ${evt.clientY}px)`;
};
#blur-around {
position: fixed;
z-index: 999;
pointer-events: none;
/* twice the viewport size so it always covers fully */
width: 200vw;
height: 200vh;
/* negative offset by half so we are sure we cover the full viewport */
left: -100vw;
top: -100vh;
/* we'll use transform translate to move it */
transform-origin: center;
-webkit-backdrop-filter: blur(15px);
backdrop-filter: blur(15px);
}
/* falback for browsers that dont have backdrop-filter */
@supports not ((backdrop-filter: blur(0px)) or (-webkit-backdrop-filter: blur(0px))) {
#blur-around {
background-color: rgba(255,255,255,.8);
}
}
<div id="blur-around"></div>
<p>Works over any content</p>
<img src="https://picsum.photos/250/250">
<img src="https://picsum.photos/360/200">
但是,backdrop-filter
目前仅在最新的 Blink + Webkit 浏览器中支持,Gecko 仍然缺乏对它的支持。由于我怀疑是否有许多其他跨浏览器解决方案,您可以尝试这个 polyfill,它将在 iframe 中复制您的页面内容(即性能不是很好)。
推荐阅读
- python - discord.py 机器人的 SQL 表中的变量更新
- swift - 如何使用 swiftUI MacOS 切换视图?
- java - 如果 WHERE 得到空结果,则抛出 UPDATE 查询异常
- c# - Xamarin Forms 网页调用从不返回结果
- android - EmptyDatabaseAlert 显示两次
- firebase - Firestore - 可以通过数组不包含查询吗?
- php - 如何从不同的域访问 SQL 数据库
- ios - iOS Swift 更新到 UI 延迟
- node.js - 适用于 windows 和 linux 的 Nodejs node-gyp 构建
- arduino - 连接到 MQTT 时,Arduino MKRGSM 1400 给出的位置不正确