# DOM操作模块
DOM操作模块提供浏览器环境下的DOM元素操作工具,包括透明度设置、图片处理等功能。
## 引用方式
### ES6 模块引用
```javascript
import sinma from 'sinmajs';
// 或者使用解构赋值
import { setOpacity, imageToBase64 } from 'sinmajs';
```
### CommonJS 引用
```javascript
const sinma = require('sinmajs');
```
### 浏览器直接引用
```html
<script src="https://unpkg.com/sinmajs@latest/dist/sinma.min.js"></script>
<script>
// 直接使用 sinma 对象
const element = document.getElementById('myDiv');
sinma.setOpacity(element, 0.5);
</script>
```
## API 列表
### setOpacity(element, opacity) - 设置元素透明度
设置DOM元素的透明度,兼容IE浏览器和现代浏览器。
#### 参数
- `element` {HTMLElement} - DOM元素对象
- `opacity` {number} - 透明度值,范围 0-1(0完全透明,1完全不透明)
#### 返回值
- {void} - 无返回值
#### 功能代码
```javascript
function setOpacity(element, opacity) {
if (!element) return;
element.style.opacity = opacity;
element.style.filter = `alpha(opacity=${opacity * 100})`;
}
```
#### 使用方法
```javascript
const element = document.getElementById('myDiv');
sinma.setOpacity(element, 0.5); // 设置为50%透明度
sinma.setOpacity(element, 0); // 完全透明
sinma.setOpacity(element, 1); // 完全不透明
sinma.setOpacity(element, 0.8); // 80%不透明度
```
#### 使用范例
```javascript
// 渐变显示效果
function fadeIn(element, duration = 1000) {
let opacity = 0;
const increment = 1 / (duration / 16); // 约60fps
sinma.setOpacity(element, 0);
element.style.display = 'block';
const timer = setInterval(() => {
opacity += increment;
if (opacity >= 1) {
opacity = 1;
clearInterval(timer);
}
sinma.setOpacity(element, opacity);
}, 16);
}
// 渐变隐藏效果
function fadeOut(element, duration = 1000) {
let opacity = 1;
const decrement = 1 / (duration / 16);
const timer = setInterval(() => {
opacity -= decrement;
if (opacity <= 0) {
opacity = 0;
sinma.setOpacity(element, 0);
element.style.display = 'none';
clearInterval(timer);
} else {
sinma.setOpacity(element, opacity);
}
}, 16);
}
// 鼠标悬停透明度变化
function setupHoverEffect(element) {
element.addEventListener('mouseenter', () => {
sinma.setOpacity(element, 0.7);
});
element.addEventListener('mouseleave', () => {
sinma.setOpacity(element, 1);
});
}
// 加载状态指示器
function showLoading(element) {
sinma.setOpacity(element, 0.3);
element.style.pointerEvents = 'none';
}
function hideLoading(element) {
sinma.setOpacity(element, 1);
element.style.pointerEvents = 'auto';
}
// 批量设置多个元素透明度
function setMultipleOpacity(selector, opacity) {
const elements = document.querySelectorAll(selector);
elements.forEach(element => {
sinma.setOpacity(element, opacity);
});
}
// 使用示例
setMultipleOpacity('.gallery-item', 0.8);
// 模态框背景遮罩
function createOverlay() {
const overlay = document.createElement('div');
overlay.style.position = 'fixed';
overlay.style.top = '0';
overlay.style.left = '0';
overlay.style.width = '100%';
overlay.style.height = '100%';
overlay.style.backgroundColor = 'black';
overlay.style.zIndex = '9999';
sinma.setOpacity(overlay, 0.5);
document.body.appendChild(overlay);
return overlay;
}
```
---
### imageToBase64(img) - 图片转Base64
将图片元素转换为Base64编码的数据URL字符串。
#### 参数
- `img` {HTMLImageElement} - 图片元素对象
#### 返回值
- {string} - Base64编码的数据URL字符串
#### 功能代码
```javascript
function imageToBase64(img) {
const canvas = document.createElement('canvas');
canvas.width = img.width || img.naturalWidth;
canvas.height = img.height || img.naturalHeight;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
return canvas.toDataURL();
}
```
#### 使用方法
```javascript
const img = document.getElementById('myImage');
const base64 = sinma.imageToBase64(img);
console.log(base64); // "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."
// 指定图片格式
const canvas = document.createElement('canvas');
// ... canvas操作
const jpegBase64 = canvas.toDataURL('image/jpeg', 0.8); // JPEG格式,质量80%
```
#### 使用范例
```javascript
// 图片上传预览
function previewImage(file, callback) {
const img = new Image();
img.onload = function() {
const base64 = sinma.imageToBase64(img);
callback(base64);
};
img.src = URL.createObjectURL(file);
}
// 使用示例
const fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', (e) => {
const file = e.target.files[0];
if (file && file.type.startsWith('image/')) {
previewImage(file, (base64) => {
const preview = document.getElementById('preview');
preview.src = base64;
});
}
});
// 图片压缩
function compressImage(img, quality = 0.8, maxWidth = 800) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// 计算压缩后的尺寸
let { width, height } = img;
if (width > maxWidth) {
height = (height * maxWidth) / width;
width = maxWidth;
}
canvas.width = width;
canvas.height = height;
// 绘制压缩后的图片
ctx.drawImage(img, 0, 0, width, height);
return canvas.toDataURL('image/jpeg', quality);
}
// 批量图片转换
function convertImagesToBase64(images) {
return Promise.all(
Array.from(images).map(img => {
return new Promise((resolve) => {
if (img.complete) {
resolve({
src: img.src,
base64: sinma.imageToBase64(img)
});
} else {
img.onload = () => {
resolve({
src: img.src,
base64: sinma.imageToBase64(img)
});
};
}
});
})
);
}
// 使用示例
const images = document.querySelectorAll('.gallery img');
convertImagesToBase64(images).then(results => {
console.log('所有图片已转换为Base64:', results);
});
// 图片水印添加
function addWatermark(img, watermarkText) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
// 绘制原图
ctx.drawImage(img, 0, 0);
// 添加水印
ctx.font = '20px Arial';
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
ctx.fillText(watermarkText, 20, canvas.height - 30);
return canvas.toDataURL();
}
// 图片缓存管理
class ImageCache {
constructor() {
this.cache = new Map();
}
getBase64(imgSrc) {
if (this.cache.has(imgSrc)) {
return Promise.resolve(this.cache.get(imgSrc));
}
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = 'anonymous';
img.onload = () => {
const base64 = sinma.imageToBase64(img);
this.cache.set(imgSrc, base64);
resolve(base64);
};
img.onerror = reject;
img.src = imgSrc;
});
}
clear() {
this.cache.clear();
}
}
const imageCache = new ImageCache();
// 图片编辑器基础功能
class SimpleImageEditor {
constructor(img) {
this.originalImg = img;
this.canvas = document.createElement('canvas');
this.ctx = this.canvas.getContext('2d');
this.reset();
}
reset() {
this.canvas.width = this.originalImg.naturalWidth;
this.canvas.height = this.originalImg.naturalHeight;
this.ctx.drawImage(this.originalImg, 0, 0);
}
adjustBrightness(factor) {
const imageData = this.ctx.getImageData(0, 0, this.canvas.width, this.canvas.height);
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
data[i] *= factor; // Red
data[i + 1] *= factor; // Green
data[i + 2] *= factor; // Blue
}
this.ctx.putImageData(imageData, 0, 0);
return this;
}
toBase64() {
return this.canvas.toDataURL();
}
}
// 使用示例
const img = document.getElementById('editImage');
const editor = new SimpleImageEditor(img);
const brightened = editor.adjustBrightness(1.2).toBase64();
```
## 高级用法示例
### 响应式图片加载
```javascript
// 响应式图片Base64转换
function createResponsiveBase64(img, breakpoints = [480, 768, 1024]) {
const results = {};
breakpoints.forEach(width => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const ratio = img.naturalHeight / img.naturalWidth;
const height = width * ratio;
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0, width, height);
results[`w${width}`] = canvas.toDataURL('image/jpeg', 0.8);
});
return results;
}
```
### 图片懒加载与透明度动画
```javascript
// 图片懒加载管理器
class LazyImageLoader {
constructor() {
this.observer = new IntersectionObserver(this.handleIntersection.bind(this));
}
observe(img) {
sinma.setOpacity(img, 0);
this.observer.observe(img);
}
handleIntersection(entries) {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
this.loadImage(img);
this.observer.unobserve(img);
}
});
}
loadImage(img) {
const tempImg = new Image();
tempImg.onload = () => {
img.src = tempImg.src;
this.fadeIn(img);
};
tempImg.src = img.dataset.src;
}
fadeIn(element) {
let opacity = 0;
const timer = setInterval(() => {
opacity += 0.05;
if (opacity >= 1) {
opacity = 1;
clearInterval(timer);
}
sinma.setOpacity(element, opacity);
}, 16);
}
}
// 使用示例
const lazyLoader = new LazyImageLoader();
document.querySelectorAll('img[data-src]').forEach(img => {
lazyLoader.observe(img);
});
```
### 图片处理工具集
```javascript
// 综合图片处理工具
class ImageProcessor {
static toGrayscale(img) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
ctx.drawImage(img, 0, 0);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
const gray = data[i] * 0.299 + data[i + 1] * 0.587 + data[i + 2] * 0.114;
data[i] = gray;
data[i + 1] = gray;
data[i + 2] = gray;
}
ctx.putImageData(imageData, 0, 0);
return canvas.toDataURL();
}
static resize(img, newWidth, newHeight) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = newWidth;
canvas.height = newHeight;
ctx.drawImage(img, 0, 0, newWidth, newHeight);
return canvas.toDataURL();
}
static crop(img, x, y, width, height) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, x, y, width, height, 0, 0, width, height);
return canvas.toDataURL();
}
}
```
## 浏览器兼容性
### setOpacity 兼容性
- **现代浏览器**: 使用 `opacity` CSS属性
- **IE 6-8**: 使用 `filter: alpha(opacity=n)`
- **完全兼容**: IE 6+ 及所有现代浏览器
### imageToBase64 兼容性
- **Canvas支持**: IE 9+ 及所有现代浏览器
- **图片跨域**: 需要设置 `crossOrigin` 属性
- **文件大小**: 受浏览器内存限制
## 性能优化建议
1. **图片缓存**: 重复转换的图片应该缓存Base64结果
2. **尺寸控制**: 大图片转换前先压缩尺寸
3. **质量平衡**: 根据使用场景选择合适的图片质量
4. **内存管理**: 及时清理不需要的Canvas元素
## 注意事项
1. **跨域问题**: 图片转Base64时注意跨域限制
2. **内存占用**: Base64编码会增加约33%的数据大小
3. **性能影响**: 大图片处理会消耗较多CPU和内存
4. **浏览器限制**: 某些浏览器对Base64长度有限制
## 错误处理
```javascript
// 安全的图片转换
function safeImageToBase64(img) {
try {
if (!img || !img.naturalWidth) {
throw new Error('无效的图片元素');
}
return sinma.imageToBase64(img);
} catch (error) {
console.error('图片转换失败:', error);
return null;
}
}
// 安全的透明度设置
function safeSetOpacity(element, opacity) {
try {
if (!element || typeof opacity !== 'number') {
throw new Error('无效的参数');
}
if (opacity < 0 || opacity > 1) {
throw new Error('透明度值必须在0-1之间');
}
sinma.setOpacity(element, opacity);
} catch (error) {
console.error('设置透明度失败:', error);
}
}
```
## 相关模块
- [字符串模块](./string.md) - 提供Base64字符串处理功能
- [工具函数模块](./utils.md) - 提供类型检查等辅助功能
- [数字模块](./number.md) - 提供数值计算功能
