Skip to content

Commit

Permalink
修改video页面瀑布图的单项样式
Browse files Browse the repository at this point in the history
  • Loading branch information
master1lan committed Jan 5, 2023
1 parent 17ba774 commit e03b2e0
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 100 deletions.
11 changes: 9 additions & 2 deletions src/components/image/image.module.less
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
.imgWrapper {
position: relative;
overflow: hidden;
border-radius: 8px;
outline: 0.5px solid rgba(0, 0, 0, .05);

&>img {
width: 100%;
display: inline-block;
border-radius: 8px;
outline: 0.5px solid rgba(0, 0, 0, .05);
object-fit: cover;
transition: opacity .5s linear;
-webkit-transition: opacity .5s linear;
transition: transform .2s linear;
-webkit-transition: transform .2s linear;

&:hover {
transform: scale(1.1);
}
}
}
6 changes: 2 additions & 4 deletions src/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@

.element-item {
min-width: 180px;

.footer {
padding: 12px;
}
box-sizing: border-box;
padding: 0 5px;
}
}
111 changes: 27 additions & 84 deletions src/routers/video/masonry.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import Image from "@components/image";
import { fetchVideos } from "@utils/fetch";
import { concurrencyRequest } from "@utils/index";
import { FC, useState, useEffect } from "react";
import SlowMotionVideoSharpIcon from "@mui/icons-material/SlowMotionVideoSharp";
import SubjectSharpIcon from "@mui/icons-material/SubjectSharp";
import Link from "@mui/material/Link";
import { concurrencyRequest, Pick } from "@utils/index";
import { useState, useEffect } from "react";
import { VideoRouterImageCardType, VideoRouterMasonryType } from "./videotype";
import { getImageSize, getResizeHeight } from "@components/image/tool";
import {
getImageSize,
getResizeHeight,
ImageSize,
} from "@components/image/tool";
import { Masonry as Masonic_masonry } from "masonic";
import ImageShouldResizeProview from "@components/proview/imageSize";
import getrealtiveTime, { getVideoTime } from "@utils/time";
import styles from "./video.module.less";
import { VideoRouterImageCard } from "./masonryItem";
/**
* @description 该组件负责渲染视频图片的瀑布流
*/
Expand All @@ -30,23 +29,25 @@ export default function VideoMasonry(props: any) {
setLists((lists) => [
...lists,
...data.map((item, index) => {
const imageSize = imageSizelists[index],
itemRes: VideoRouterImageCardType = {
title: item.title,
bvid: item.bvid,
name: item.name,
tname: item.tname,
copyright: item.copyright,
pic: item.pic,
tag: item.tag,
view: item.view,
coin: item.coin,
share: item.share,
like: item.like,
updated_at: item.updated_at,
danmaku: item.danmaku,
duration: item.duration,
};
const imageSize: ImageSize = imageSizelists[index],
itemRes: VideoRouterImageCardType = Pick(
item,
"title",
"bvid",
"name",
"tname",
"copyright",
"pic",
"tag",
"view",
"coin",
"share",
"like",
"updated_at",
"danmaku",
"duration"
);

if (imageSize.success === true) {
return {
...itemRes,
Expand All @@ -67,7 +68,6 @@ export default function VideoMasonry(props: any) {
items={lists}
columnWidth={order_width}
rowGutter={10}
columnGutter={10}
maxColumnCount={5}
render={VideoRouterImageCard}
overscanBy={Infinity}
Expand All @@ -76,60 +76,3 @@ export default function VideoMasonry(props: any) {
</div>
);
}

const VideoRouterImageCard: FC<{ data: VideoRouterImageCardType }> = ({
data: {
pic,
bvid,
name,
tname,
title,
tag,
view,
coin,
share,
like,
updated_at,
danmaku,
duration,
...res
},
}) => {
return (
<section className='element-item'>
<Image url={pic} {...res}>
<div className={styles["video-data"]}>
<div className={styles["video-data-left"]}>
<span>
<SlowMotionVideoSharpIcon fontSize='small' />
{view}
</span>
<span>
<SubjectSharpIcon fontSize='small' />
{danmaku}
</span>
</div>
<span>{getVideoTime(duration)}</span>
</div>
</Image>
<div className={styles["video-info"]}>
<p title={title}>
<Link
target='_blank'
href={`https://www.bilibili.com/video/${bvid}`}
underline='none'
color='inherit'
>
{title}
</Link>
</p>
<div className={styles["video-up-info"]}>
<Link underline='none' color='inherit'>
<span title={name}>{name}</span>
<span>{getrealtiveTime(updated_at * 1000)}</span>
</Link>
</div>
</div>
</section>
);
};
95 changes: 95 additions & 0 deletions src/routers/video/masonryItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import Image from "@components/image";
import { FC } from "react";
import SlowMotionVideoSharpIcon from "@mui/icons-material/SlowMotionVideoSharp";
import SubjectSharpIcon from "@mui/icons-material/SubjectSharp";
import Link from "@mui/material/Link";
import { VideoRouterImageCardType } from "./videotype";
import getrealtiveTime, { getVideoTime } from "@utils/time";
import styles from "./video.module.less";
import { Omit, Pick } from "@utils/index";

export const VideoRouterImageCard: FC<{ data: VideoRouterImageCardType }> = ({
data,
}) => {
const { pic, bvid } = data;
return (
<section className='element-item'>
<Link
target='_blank'
href={`https://www.bilibili.com/video/${bvid}`}
underline='none'
color='inherit'
>
<Image
url={pic}
{...Omit(
data,
"pic",
"bvid",
"name",
"tname",
"title",
"tag",
"view",
"coin",
"share",
"like",
"updated_at",
"danmaku",
"duration"
)}
>
{/* todo:lost tag */}
<VideoData {...Pick(data, "view", "danmaku", "duration")} />
</Image>
</Link>
<VideoInfo {...Pick(data, "title", "name", "updated_at", "bvid")} />
</section>
);
};
const VideoData: FC<
Pick<VideoRouterImageCardType, "view" | "danmaku" | "duration">
> = (props) => {
const { view, danmaku, duration } = props;
return (
<div className={styles["video-data"]}>
<div className={styles["video-data-left"]}>
<span title='播放量'>
<SlowMotionVideoSharpIcon fontSize='small' />
{view}
</span>
<span title='弹幕数'>
<SubjectSharpIcon fontSize='small' />
{danmaku}
</span>
</div>
<span title='视频时长'>{getVideoTime(duration)}</span>
</div>
);
};
const VideoInfo: FC<
Pick<VideoRouterImageCardType, "title" | "name" | "updated_at" | "bvid">
> = (props) => {
const { title, name, bvid, updated_at } = props;
return (
<div className={styles["video-info"]}>
<p title={title}>
<Link
target='_blank'
href={`https://www.bilibili.com/video/${bvid}`}
underline='none'
color='inherit'
>
{title}
</Link>
</p>
<div className={styles["video-up-info"]}>
<Link underline='none' color='inherit'>
<span title={name}>{name}</span>
<span>{getrealtiveTime(updated_at * 1000)}</span>
</Link>
</div>
</div>
);
};
// 1-6 todo:写完视频页面展示瀑布图
56 changes: 46 additions & 10 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,22 +84,58 @@ export function concurrencyRequest<T>(
});
}

export function Pick<T extends object>(originObj: T, ...getAttr: (keyof T)[]) {
let res = {};
//@ts-ignore
getAttr.forEach((value) => (res[value] = originObj[value]));
return res;
/**
* @description Pick函数,将对象中的某些属性抽离出来返回一个新对象
*/
export function Pick<T extends object, P extends keyof T>(
originObj: T,
...getAttr: P[]
): Pick<T, P> {
return getAttr.reduce((pre, cur) => {
pre[cur] = originObj[cur];
return pre;
}, Object.create(null));
}

type test = keyof {
a: number;
b: number;
};
/**
* @description Omit函数,将对象中的某些属性剔除返回一个新对象
*/
export function Omit<T extends object, P extends keyof T>(
originObj: T,
...noUseAttr: P[]
): Omit<T, P> {
return noUseAttr.reduce((pre, cur) => {
delete pre[cur];
return pre;
}, deepClone(originObj));
}

/**
* 节流函数,指连续触发事件但是在 n 秒中只执行一次函数
* @description 深拷贝对象
*/
export function deepClone(obj: any, hash = new WeakMap()) {
if (obj === null) return obj; // 如果是null或者undefined我就不进行拷贝操作
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
// 可能是对象或者普通的值 如果是函数的话是不需要深拷贝
if (typeof obj !== "object") return obj;
// 是对象的话就要进行深拷贝
if (hash.get(obj)) return hash.get(obj);
let cloneObj = new obj.constructor();
// 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身
hash.set(obj, cloneObj);
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
// 实现一个递归拷贝
cloneObj[key] = deepClone(obj[key], hash);
}
}
return cloneObj;
}

/**
* @description 节流函数,指连续触发事件但是在 n 秒中只执行一次函数
*/
export function thorttleFn<T extends (...args: any) => any>(
fn: T,
absTime: number = 3000
Expand Down

0 comments on commit e03b2e0

Please sign in to comment.