0.0.67 • Published 11 months ago

img-mark v0.0.67

Weekly downloads
-
License
MIT
Repository
github
Last release
11 months ago

Img-Mark

在一个图片中标记一个或者多个截图区域

在截图区域中标记一个或者多个子区域

如下图:

npm.io

使用

引入样式

//main.ts
import 'img-mark/dist/style.css'

示例

<template>
	<div class="page-test-img-mark">
		<div style="width: 50vw; height: 100vh; background: #ccc; box-sizing: border-box; flex-shrink: 0">
			<ImgMark
				ref="imgMarkRef"
				:src="src"
				v-model:mode="mode"
				v-model:tagList="tagList"
				v-model:cropList="cropList"
				:enableDrawCropOutOfImg="false"
				:enableDrawTagOutOfCrop="false"
				:enableDrawTagOutOfImg="false"
			></ImgMark>
		</div>
		<div class="info-panel">
			<el-input v-model="src"></el-input>
			<el-button type="primary" size="small" style="margin-top: 40px" @click="getGroupInfo()">getGroupInfo</el-button>
			<el-alert
				v-for="item in tagList"
				@close="removeTag([item])"
				@mouseenter="setHoverItem(item)"
				@mouseleave="removeHoverItem(item)"
				style="margin-top: 20px"
				:key="uid(6)"
				:title="JSON.stringify(item)"
				type="warning"
			>
			</el-alert>
		</div>
	</div>
</template>
<script setup lang="ts">
import { ImgMark, Mode, BoundingBox } from 'img-mark'
import { uid } from 'uid'
let src = $ref('https://forza.ismcdn.jp/mwimgs/8/e/1774n/img_8e8307dc5355e41385fd3568ef95f233218536.jpg')
let mode = $ref<Mode>('crop')
let cropList = $ref<BoundingBox[]>([
	{
		startX: 0,
		startY: 0,
		endX: 1774,
		endY: 100,
	},
	{
		startX: 200,
		startY: 200,
		endX: 1000,
		endY: 500,
	},
])

let tagList = $ref<BoundingBox[]>([
	{
		startX: 50,
		startY: 0,
		endX: 100,
		endY: 50,
		isShow: true,
		labelText: 'customTagLabelText',
	},
	{
		startX: 0,
		startY: 0,
		endX: 1774,
		endY: 100,
		isShow: true,
	},
])

let imgMarkRef = $ref<InstanceType<typeof ImgMark>>()

function removeTag(data?: BoundingBox[]) {
	if (data) {
		imgMarkRef.removeTagItems(data)
	}
}
function cropChange() {
	removeTag()
}

function setHoverItem(item: BoundingBox) {
	item.showOutLine = true
}
function removeHoverItem(item: BoundingBox) {
	item.showOutLine = false
}

function getGroupInfo() {
	let groupInfo = imgMarkRef.getTagListGroupByCropIndex()
	console.log(groupInfo)
}
</script>
<style scoped lang="scss">
.page-test-img-mark {
	display: flex;
	justify-content: space-between;
	.info-panel {
		width: 50vw;
		box-sizing: border-box;
		padding: 20px;
	}
}
</style>

类型

type ShortCutItem = 'ctrl+b' | 'space'

type Event = {
	onClick?: (e: unknown, item: BoundingBox) => void //tag click事件
	onDoubleClick?: (e: unknown, item: BoundingBox) => void //tag double click事件
}

type Hooks = {
	shiftMode(): void //切换模式
	shiftDrawSwitch(onOrOff: 'on' | 'off'): void //切换是否开始画的开关
	init(): void //初始化组件
	resize(): void //resize后重新初始化组件
}

type BoundingBox = {
	startX: number
	endX: number
	startY: number
	endY: number
	isShow?: boolean //tag是否显示
	showOutLine?: boolean //tag是否边框是否高亮
	labelText?: string //tag的标签文字
	tagConfig?: TagConfig //单独定义某个tagConfig
	cropConfig?: CropConfig //单独定义某个cropConfig
} & Event

type CropConfig = {
	lineDash?: number[]
	strokeStyle?: string
	lineWidth?: number
	customDraw?: CustomDraw
}

export type DaubConfig = {
	strokeStyle?: string
	lineWidth?: number
}

type LayerConfig = {
	fillStyle?: string
}

export type CustomDraw = (
	ctx: CanvasRenderingContext2D,
	info: {
		target: BoundingBox | undefined
		positions: Rect
	}
) => void

type TagConfig = {
	fontSize?: number //px单位,默认20
	showText?: boolean //是否展示tag index
	fillStyle?: string
	textFillStyle?: string
	hoverStrokeStyle?: string
	hoverLineWidth?: number
	hoverLineDash?: number[]
	highlightStrokeStyle?: string
	highlightLineWidth?: number
	highlightLineDash?: number[]
	customDraw?: CustomDraw
}

type Point = {
	x: number
	y: number
}

export type DaubPoint = Point & {
	lineWidth?: number
	strokeStyle?: string
}

type ResizeEmitType = {
	index: number
	box: BoundingBox
}

type TagListGroupByCropIndex = {
	[key: number]: BoundingBox[]
	undefined: BoundingBox[]
}

type MouseOverInfoEmitType = {
	canvas: Point | null
	img: Point | null
}

type OnLoadImageEmitType = {
	status: 'loading' | 'success' | 'error'
	msg?: string
}

type TagListChangeType = 'add' | 'delete' | 'statusChange'

type TagListChangeEmitRetunType = {
	type: TagListChangeType
	list: BoundingBox[]
	parentCrop?: BoundingBox
}

type CropListChangeType = 'add' | 'delete' | 'resize'

type CropListChangeEmitType = {
	type: CropListChangeType
	list: BoundingBox[]
}

type BoundingBox2Rect = (boundingBoxList: BoundingBox[]) => Rect[]
type CustomDrawTopCtx = (ctx: CanvasRenderingContext2D, boundingBox2Rect: BoundingBox2Rect) => void

组件属性

属性说明类型可选值默认值
src图片地址, 必选参数string————
mode/v-model:mode模式stringcrop/tag/daubcrop
mobileOperation/v-model:mobileOperation移动端单指在画布滑动是移动还是画 rectstringmove/drawmove
cropList/v-model:cropList裁切区域集合,相对于img左上角开始定位BoundingBox[]——[]
tagList/v-model:tagListtag 区域集合,相对于img左上角开始定位BoundingBox[]——[]
daubStack/v-model:daubStack涂抹区域店集合,相对于img左上角开始定位DaubPoint——[]
precisionBoundingBox 精度number——0
drawingTexttag时候展示的文字number——0
initScale是否自动缩放图片适应到画布大小booleantrue/falsetrue
enableScale是否允许缩放画布booleantrue/falsetrue
enableMove是否允许移动画布booleantrue/falsetrue
enableDrawCrop是否允许在画布上画 cropbooleantrue/falsetrue
enableDrawTag是否允许在画布上画 tagbooleantrue/falsetrue
enableInteractiveTagChangeStatus是否允许交互改变 tag 状态booleantrue/falsetrue
enableInteractiveCropDelete是否允许交互删除 cropbooleantrue/falsetrue
enableDrawCropOutOfImg是否允许 crop 画到图片外booleantrue/falsetrue
enableDrawTagOutOfCrop是否允许 tag 画到 cropbooleantrue/falsetrue
enableDrawTagOutOfImg是否允许 tag 画到图片外booleantrue/falsetrue
splitClickAndDoubleClickEvent是否分离单击和双击事件booleantrue/falsefalse
disableDefaultShortcuts禁用默认快捷键ShortCutItem[]——[]
enableCropResize是否允许 crop 改变大小booleantrue/falsetrue
enableTagResize是否允许 tag 改变大小booleantrue/falsefalse
enableCropCross是否允许 crop 和其他 crop 相交,不允许后,如果相交,新画的crop会不添加,如果是 resize 操作相交以后,按照下方 handleResizeCropCross 属性去处理booleantrue/falsetrue
handleResizeCropCrossenableCropCross属性为 false,resize 操作相交后该如何处理进行 resize 操作的cropstringdelete/resetreset
isShowTip是否显示底部提示区域booleantrue/falsefalse
isCropSingle是否单个 crop , 在添加 crop 的时候自动删除旧的 cropbooleantrue/falsefalse
isImgCrop是否在 cropList 为空时默认以图片大小为裁切区域booleantrue/falsefalse
layerConfig浮层样式LayerConfig————
cropConfigcrop 样式CropConfig————
tagConfigtag 样式TagConfig————
daubConfigdaub 样式DaubConfig————
customDrawTopCtx自定义绘制CustomDrawTopCtx————

组件事件

事件名说明参数
tagListChange当添加或者删除或者改变组件状态 tag 项触发,parentCrop 只在 typeadd 时候返回data:TagListChangeEmitRetunType
cropListChange当添加或者删除或者改变 crop 大小触发{type:'add'/'delete'/'resize', list:BoundingBox[] }
resizeStartcrop 开始 resize 触发data:ResizeEmitType
resizeEndcrop 结束 resize 触发data:ResizeEmitType
delCrop删除 crop 触发list:BoundingBox[]
drawCropStart添加 crop 之前触发——
drawTagStart添加 tag 之前触发——
mouseOverInfo鼠标在组件上移动或者移除时候触发info:MouseOverInfoEmitType
onLoadImage图片加载状态事件data:OnLoadImageEmitType

组件暴露对象

对象类型说明
hooksHooks调用组件抽象方法

组件暴露方法

方法说明参数返回类型
removeTagItems移除 taglist:BoundingBox[]void
render重新渲染——void
getTagListGroupByCropIndex获取 tagList 并按照 cropIndex 分组type: 'startPoint'/'allIn' = 'startPoint'TagListGroupByCropIndex
getBase64ImageData获取原图大小绘制完各种元素后的 base64 图片 urlcrossOrigin?: booleanPromise\
scrollIntoView讲某个区域滚动到 0,0 点box: BoundingBoxvoid

Slots

插槽名说明
tip右下角提示自定义内容

Lib 方法

方法说明参数返回类型
transformTagListBoxRelativeTo转换 tag list 基于什么去定位type: 'img'/'crop', cropInfo: BoundingBox, tagList: BoundingBox[]BoundingBox[]
transformTagBoxRelativeTo转换单个 tag 基于什么去定位type: 'img'/'crop', cropInfo: BoundingBox, tag: BoundingBoxBoundingBox
boxIsAllInOtherBoxbox 是否完全包含在另一个 boxbox: BoundingBox, otherBox: BoundingBoxboolean

操作

移动画布

按住鼠标左键拖动

画区域

按下空格 + 按住鼠标左键拖动

切换模式

Ctrl + B

放大缩小

鼠标滚轮

0.0.62

12 months ago

0.0.63

12 months ago

0.0.64

11 months ago

0.0.65

11 months ago

0.0.66

11 months ago

0.0.67

11 months ago

0.0.60

1 year ago

0.0.61

1 year ago

0.0.59

1 year ago

0.0.58

1 year ago

0.0.54

2 years ago

0.0.55

2 years ago

0.0.56

2 years ago

0.0.57

2 years ago

0.0.45

2 years ago

0.0.46

2 years ago

0.0.47

2 years ago

0.0.51

2 years ago

0.0.52

2 years ago

0.0.53

2 years ago

0.0.50

2 years ago

0.0.48

2 years ago

0.0.49

2 years ago

0.0.41

2 years ago

0.0.42

2 years ago

0.0.43

2 years ago

0.0.44

2 years ago

0.0.40

2 years ago

0.0.37

2 years ago

0.0.38

2 years ago

0.0.39

2 years ago

0.0.35

2 years ago

0.0.36

2 years ago

0.0.30

2 years ago

0.0.31

2 years ago

0.0.32

2 years ago

0.0.33

2 years ago

0.0.34

2 years ago

0.0.27

2 years ago

0.0.28

2 years ago

0.0.29

2 years ago

0.0.25

2 years ago

0.0.26

2 years ago

0.0.24

2 years ago

0.0.23

2 years ago

0.0.22

2 years ago

0.0.21

2 years ago

0.0.20

2 years ago

0.0.19

2 years ago

0.0.18

2 years ago

0.0.17

2 years ago

0.0.16

2 years ago

0.0.15

2 years ago

0.0.14

2 years ago

0.0.13

2 years ago

0.0.12

2 years ago

0.0.11

2 years ago

0.0.10

2 years ago

0.0.9

2 years ago

0.0.8

2 years ago

0.0.7

2 years ago

0.0.6

2 years ago

0.0.5

2 years ago

0.0.4

2 years ago

0.0.3

2 years ago

0.0.2

2 years ago

0.0.1

2 years ago