vue-photo-commenter
v1.0.6
Published
A Vue component for adding comments to specific areas of an image
Readme
Vue Photo Commenter
A Vue 3 component for adding comments to images with pin markers.
Features
- Draw selection boxes on images to add comments
- Hover over comment boxes to see comments
- Click on comment boxes to highlight them
- Click on comments in the list to highlight corresponding boxes on the image
- Responsive design that works with any image size
- Built with Element Plus UI components
- TypeScript support
- Customizable comments section component
Installation
npm install vue-photo-commenterUsage
<template>
<PhotoCommenter
:image-url="imageUrl"
v-model="comments"
:author="author"
@submit="handleSubmit"
@cancel="handleCancel"
/>
</template>
<script setup>
import { ref } from 'vue'
import PhotoCommenter from 'vue-photo-commenter'
import 'vue-photo-commenter/dist/photo-commenter.css'
import { ElMessage, ElLoading } from 'element-plus'
import 'element-plus/dist/index.css'
const imageUrl = 'https://example.com/image.jpg'
const comments = ref([])
const author = ref({
userId: 'user123',
name: 'John Doe',
email: '[email protected]'
})
const handleSubmit = (newComments) => {
comments.value = newComments
}
const handleCancel = () => {
console.log('Comment input cancelled')
}
</script>Props
| Prop | Type | Required | Default | Description | |------|------|----------|---------|-------------| | imageUrl | string | Yes | - | URL of the image to comment on | | modelValue | CommentData[] | Yes | [] | Array of comments (v-model) | | author | Author | Yes | - | Current user's author information | | selectedComment | number | No | null | Index of the currently selected comment |
Events
| Event | Payload | Description | |-------|---------|-------------| | update:modelValue | CommentData[] | Emitted when comments are updated | | submit | CommentData[] | Emitted when a new comment is submitted | | cancel | - | Emitted when comment input is cancelled | | box-click | number | Emitted when a comment box is clicked |
Types
interface Author {
userId: string
name: string
email: string
role?: string
}
interface CommentData {
x: number
y: number
width: number
height: number
text: string
author: Author
created_date: string
replies?: CommentData[]
}Components
PhotoCommenter
The main component for adding comments to images.
Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| imageUrl | String | Yes | The URL of the image to display |
| value | Array | No | Array of comments (v-model) |
| selectedComment | Number | No | Index of the currently selected comment |
Events
| Event | Description | Parameters |
|-------|-------------|------------|
| update:value | Emitted when comments are updated | Array of comments |
| submit | Emitted when a new comment is saved | Array of comments |
| cancel | Emitted when comment input is cancelled | None |
CommentsSection
A component to display the list of comments with customizable styling.
Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| comments | Array | Yes | Array of comments to display |
| styles | Object | No | Custom styles for different parts of the component |
| selectedIndex | Number | No | Index of the currently selected comment |
Style Properties
The styles prop accepts an object with the following properties:
interface StyleProps {
sectionStyles?: CSSProperties; // Styles for the main container
titleStyles?: CSSProperties; // Styles for the "Comments" title
listStyles?: CSSProperties; // Styles for the comments list
commentStyles?: CSSProperties; // Styles for each comment item
contentStyles?: CSSProperties; // Styles for the comment text
authorStyles?: CSSProperties; // Styles for the author information
}Events
| Event | Description | Parameters |
|-------|-------------|------------|
| comment-click | Emitted when a comment is clicked | Index of the clicked comment |
Slots
| Slot | Description | Props |
|------|-------------|-------|
| comment | Custom template for each comment | { comment: CommentData } |
Comment Object Structure
Each comment in the array has the following structure:
interface Comment {
x: number; // X position (0-1)
y: number; // Y position (0-1)
width: number; // Width (0-1)
height: number; // Height (0-1)
text: string; // Comment text
created_date: string; // ISO date string
}Dependencies
- Vue 3
- Element Plus
Example
Here's a complete example of how to use both components with comment highlighting:
<template>
<div class="container">
<h1>Image Commenter Demo</h1>
<PhotoCommenter
:image-url="imageUrl"
v-model="comments"
:selected-comment="selectedCommentIndex"
@submit="handleSubmit"
@cancel="handleCancel"
/>
<CommentsSection
:comments="comments"
:selected-index="selectedCommentIndex"
@comment-click="handleCommentClick"
:styles="{
titleStyles: { color: '#333', fontSize: '1.5em' },
listStyles: { marginTop: '20px' },
commentStyles: {
backgroundColor: '#f5f5f5',
padding: '15px',
borderRadius: '8px',
marginBottom: '15px'
}
}"
>
<template #comment="{ comment }">
<div class="custom-comment">
<p class="comment-text">{{ comment.text }}</p>
<small class="comment-date">
Added on: {{ new Date(comment.created_date).toLocaleDateString() }}
</small>
</div>
</template>
</CommentsSection>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { PhotoCommenter, CommentsSection } from 'vue-photo-commenter'
import 'vue-photo-commenter/dist/photo-commenter.css'
const imageUrl = 'https://example.com/your-image.jpg'
const comments = ref([])
const selectedCommentIndex = ref(null)
const handleSubmit = (newComments) => {
console.log('Comments updated:', newComments)
}
const handleCancel = () => {
console.log('Comment input cancelled')
}
const handleCommentClick = (index) => {
selectedCommentIndex.value = index
}
</script>
<style scoped>
.container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.custom-comment {
display: flex;
flex-direction: column;
gap: 8px;
}
.comment-text {
margin: 0;
font-size: 1.1em;
}
.comment-date {
color: #666;
font-size: 0.9em;
}
</style>License
MIT
