mirror of
https://gitee.com/LongbowEnterprise/BootstrapBlazor.git
synced 2024-11-29 18:49:08 +08:00
feat(ImageViewer): add IsIntersectionObserver parameter (#3602)
* refactor: 重构代码消除警告信息 * doc: 代码格式化 * refactor: 脚本所需参数移动到 option 减少 html 渲染 * feat: 增加 IsIntersectionObserver 参数 * doc: 更新示例 * doc: 增加示例 * doc: 更新文档 * test: 增加单元测试 * test: 更新单元测试
This commit is contained in:
parent
a21687cf6d
commit
2c7d9deb35
@ -85,3 +85,4 @@ dbcell
|
||||
autoredirect
|
||||
Searchs
|
||||
meili
|
||||
onerror
|
||||
|
@ -2,7 +2,9 @@
|
||||
<a href="@Url">
|
||||
<div class="card">
|
||||
<div class="card-header">@Text</div>
|
||||
<div class="card-body"><img alt="url" src="@ImageUrl" /></div>
|
||||
<div class="card-body">
|
||||
<ImageViewer Url="@ImageUrl" IsIntersectionObserver="true" IsAsync="true" />
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -127,4 +127,10 @@
|
||||
<ImagePreviewer @ref="ImagePreviewer" PreviewList="PreviewList"></ImagePreviewer>
|
||||
</DemoBlock>
|
||||
|
||||
<DemoBlock Title="@Localizer["IntersectionObserverTitle"]"
|
||||
Introduction="@Localizer["IntersectionObserverIntro"]"
|
||||
Name="IsIntersectionObserver">
|
||||
<ImageViewer Url="./images/tutorials/waterfall.png" IsIntersectionObserver="true" IsAsync="true" style="height: 400px;"></ImageViewer>
|
||||
</DemoBlock>
|
||||
|
||||
<AttributeTable Items="@GetAttributes()" />
|
||||
|
@ -95,6 +95,13 @@ public partial class ImageViewers
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
},
|
||||
new() {
|
||||
Name = nameof(ImageViewer.IsIntersectionObserver),
|
||||
Description = Localizer["ImageViewersAttrIsIntersectionObserver"],
|
||||
Type = "bool",
|
||||
ValueList = "true/false",
|
||||
DefaultValue = "false"
|
||||
},
|
||||
new() {
|
||||
Name = nameof(ImageViewer.OnLoadAsync),
|
||||
Description = Localizer["ImageViewersAttrOnLoadAsync"],
|
||||
|
@ -5593,6 +5593,7 @@
|
||||
"ImageViewersAttrPreviewList": "A larger preview link set",
|
||||
"ImageViewersAttrOnLoadAsync": "The callback method picture when it is loaded successfully",
|
||||
"ImageViewersAttrOnErrorAsync": "Images load failed callback methods",
|
||||
"ImageViewersAttrIsIntersectionObserver": "Images lazy loading by view window",
|
||||
"ImageViewerNormalTips1": "<code>object-fit: fill</code> Fill the default drawing picture to fill the whole container, does not guarantee that keep the original proportion",
|
||||
"ImageViewerNormalTips2": "<code>object-fit: contain</code> Contains keep original size scaling to ensure the whole image can be appeared in the container, so this parameter may be left blank in the container",
|
||||
"ImageViewerNormalTips3": "<code>object-fit: cover</code> Cover to keep the original size scaling, width and height of at least one consistent and containers (size small) so this parameter may let image section area is not visible",
|
||||
@ -5611,7 +5612,9 @@
|
||||
"ImageViewerErrorTemplateLoadFailed": "Load failed",
|
||||
"ImagePreviewerTitle": "Use ImagePreviewer Standalone",
|
||||
"ImagePreviewerIntro": "Pop up the Previewer directly in conjunction with other components like Button",
|
||||
"ImagePreviewerButton": "Show Previewer"
|
||||
"ImagePreviewerButton": "Show Previewer",
|
||||
"IntersectionObserverTitle": "Intersection Observer",
|
||||
"IntersectionObserverIntro": "By setting <code>IsIntersectionObserver=\"true\"</code> to enable lazy loading, the image will not be loaded when it is in the invisible area, and will be loaded only when it is about to be visible."
|
||||
},
|
||||
"BootstrapBlazor.Server.Components.Samples.Geolocations": {
|
||||
"GeolocationsTitle": "Geolocation",
|
||||
|
@ -5593,6 +5593,7 @@
|
||||
"ImageViewersAttrPreviewList": "预览大图链接集合",
|
||||
"ImageViewersAttrOnLoadAsync": "图片加载成功时回调方法",
|
||||
"ImageViewersAttrOnErrorAsync": "图片加载失败时回调方法",
|
||||
"ImageViewersAttrIsIntersectionObserver": "图片懒加载",
|
||||
"ImageViewerNormalTips1": "<code>object-fit: fill</code> 填充 默认值 使图片拉伸填满整个容器, 不保证保持原有的比例",
|
||||
"ImageViewerNormalTips2": "<code>object-fit: contain</code> 包含 保持原有尺寸比例缩放 保证整个图片都可以出现在容器中,因此此参数可能会在容器内留下空白",
|
||||
"ImageViewerNormalTips3": "<code>object-fit: cover</code> 覆盖 保持原有尺寸比例缩放,宽度和高度至少有一个和容器一致(尺寸小的一致)因此此参数可能会让图片部分区域不可见",
|
||||
@ -5609,9 +5610,11 @@
|
||||
"ImageViewerErrorTemplateUrlError": "Url 路径错误",
|
||||
"ImageViewerErrorTemplateCustom": "自定义",
|
||||
"ImageViewerErrorTemplateLoadFailed": "加载失败",
|
||||
"ImagePreviewerTitle": "单独使用ImagePreviewer",
|
||||
"ImagePreviewerIntro": "配合Button等其他组件,直接弹出Previewer",
|
||||
"ImagePreviewerButton": "显示Previewer"
|
||||
"ImagePreviewerTitle": "单独使用 ImagePreviewer",
|
||||
"ImagePreviewerIntro": "配合 <code>Button</code> 等其他组件,直接弹出 <code>ImagePreviewer</code>",
|
||||
"ImagePreviewerButton": "显示 Previewer",
|
||||
"IntersectionObserverTitle": "懒加载",
|
||||
"IntersectionObserverIntro": "通过设置 <code>IsIntersectionObserver=\"true\"</code> 开启懒加载特性,当图片在不可见区域时不加载图片,当图片即将可见时才开始加载图片"
|
||||
},
|
||||
"BootstrapBlazor.Server.Components.Samples.Geolocations": {
|
||||
"GeolocationsTitle": "地理定位/移动距离追踪",
|
||||
|
@ -2,7 +2,7 @@
|
||||
@inherits BootstrapModuleComponentBase
|
||||
@attribute [BootstrapModuleAutoLoader]
|
||||
|
||||
<div @attributes="AdditionalAttributes" class="@ClassString" id="@Id" data-bb-previewer-id="@PreviewerId" data-bb-async="@IsAsyncString">
|
||||
<div @attributes="AdditionalAttributes" class="@ClassString" id="@Id">
|
||||
@if (ShowImage)
|
||||
{
|
||||
@RenderChildContent()
|
||||
|
@ -110,6 +110,13 @@ public partial class ImageViewer
|
||||
[Parameter]
|
||||
public string? FileIcon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 是否交叉监听 默认 false
|
||||
/// </summary>
|
||||
/// <remarks>不可见时不加载图片,当图片即将可见时才开始加载图片</remarks>
|
||||
[Parameter]
|
||||
public bool IsIntersectionObserver { get; set; }
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private IIconTheme? IconTheme { get; set; }
|
||||
@ -120,8 +127,6 @@ public partial class ImageViewer
|
||||
|
||||
private bool IsError { get; set; }
|
||||
|
||||
private string? IsAsyncString => IsAsync ? "true" : null;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
@ -152,7 +157,7 @@ public partial class ImageViewer
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Url, PreviewList, PreviewIndex);
|
||||
protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, new { Url, PreviewList, PreviewIndex, Async = IsAsync, PreviewerId, Intersection = IsIntersectionObserver });
|
||||
|
||||
private RenderFragment RenderChildContent() => builder =>
|
||||
{
|
||||
@ -160,7 +165,7 @@ public partial class ImageViewer
|
||||
{
|
||||
builder.OpenElement(0, "img");
|
||||
builder.AddAttribute(1, "class", ImageClassString);
|
||||
if (!IsAsync)
|
||||
if (!IsAsync && !IsIntersectionObserver)
|
||||
{
|
||||
builder.AddAttribute(2, "src", Url);
|
||||
}
|
||||
@ -207,7 +212,7 @@ public partial class ImageViewer
|
||||
|
||||
private bool ShouldHandleError => HandleError || ErrorTemplate != null;
|
||||
|
||||
private bool ShowPreviewList => PreviewList?.Any() ?? false;
|
||||
private bool ShowPreviewList => PreviewList != null && PreviewList.Count > 0;
|
||||
|
||||
private string PreviewerId => $"prev_{Id}";
|
||||
private string? PreviewerId => ShowPreviewList ? $"prev_{Id}" : null;
|
||||
}
|
||||
|
@ -14,24 +14,37 @@ const setListeners = (viewer, index) => {
|
||||
}
|
||||
}
|
||||
|
||||
export function init(id, url, preList, index) {
|
||||
export function init(id, options) {
|
||||
const el = document.getElementById(id)
|
||||
if (el === null) {
|
||||
return
|
||||
}
|
||||
|
||||
const { url, preList, index, async, previewerId, intersection } = options;
|
||||
const viewer = {
|
||||
element: el,
|
||||
img: el.querySelector('img'),
|
||||
async: el.getAttribute('data-bb-async'),
|
||||
async: async,
|
||||
prevList: preList || [],
|
||||
previewerId: el.getAttribute('data-bb-previewer-id')
|
||||
previewerId: previewerId
|
||||
}
|
||||
if (url) {
|
||||
viewer.prevList.push(url)
|
||||
}
|
||||
Data.set(id, viewer)
|
||||
|
||||
if (viewer.img && viewer.async) {
|
||||
if (intersection) {
|
||||
let observer = new IntersectionObserver(enteries => {
|
||||
const entry = enteries[0];
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.setAttribute('src', url);
|
||||
observer.unobserve(entry.target);
|
||||
observer = null;
|
||||
}
|
||||
});
|
||||
observer.observe(viewer.img);
|
||||
}
|
||||
else if (viewer.img && viewer.async) {
|
||||
viewer.img.setAttribute('src', url)
|
||||
}
|
||||
|
||||
@ -45,7 +58,7 @@ export function update(id, prevList, index) {
|
||||
}
|
||||
|
||||
viewer.prevList = prevList
|
||||
setListeners(viewer,index)
|
||||
setListeners(viewer, index)
|
||||
}
|
||||
|
||||
export function dispose(id) {
|
||||
|
@ -122,6 +122,17 @@ public class ImageTest : BootstrapBlazorTestBase
|
||||
cut.Contains("bb-previewer collapse active");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsIntersectionObserver_Ok()
|
||||
{
|
||||
var cut = Context.RenderComponent<ImageViewer>(pb =>
|
||||
{
|
||||
pb.Add(a => a.Url, "https://www.blazor.zone/images/logo.png");
|
||||
pb.Add(a => a.IsIntersectionObserver, true);
|
||||
});
|
||||
cut.DoesNotContain("src");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImagerViewer_Show()
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user