# DOM操作模塊
DOM操作模塊提供瀏覽器環(huán)境下的DOM元素操作工具,包括透明度設(shè)置、圖片處理等功能。
## 引用方式
### ES6 模塊引用
```javascript
import sinma from 'sinmajs';
// 或者使用解構(gòu)賦值
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) - 設(shè)置元素透明度
設(shè)置DOM元素的透明度,兼容IE瀏覽器和現(xiàn)代瀏覽器。
#### 參數(shù)
- `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); // 設(shè)置為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);
}
// 鼠標(biāo)懸停透明度變化
function setupHoverEffect(element) {
element.addEventListener('mouseenter', () => {
sinma.setOpacity(element, 0.7);
});
element.addEventListener('mouseleave', () => {
sinma.setOpacity(element, 1);
});
}
// 加載狀態(tài)指示器
function showLoading(element) {
sinma.setOpacity(element, 0.3);
element.style.pointerEvents = 'none';
}
function hideLoading(element) {
sinma.setOpacity(element, 1);
element.style.pointerEvents = 'auto';
}
// 批量設(shè)置多個(gè)元素透明度
function setMultipleOpacity(selector, opacity) {
const elements = document.querySelectorAll(selector);
elements.forEach(element => {
sinma.setOpacity(element, opacity);
});
}
// 使用示例
setMultipleOpacity('.gallery-item', 0.8);
// 模態(tài)框背景遮罩
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) - 圖片轉(zhuǎn)Base64
將圖片元素轉(zhuǎn)換為Base64編碼的數(shù)據(jù)URL字符串。
#### 參數(shù)
- `img` {HTMLImageElement} - 圖片元素對象
#### 返回值
- {string} - Base64編碼的數(shù)據(jù)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格式,質(zhì)量80%
```
#### 使用范例
```javascript
// 圖片上傳預(yù)覽
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');
// 計(jì)算壓縮后的尺寸
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);
}
// 批量圖片轉(zhuǎn)換
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('所有圖片已轉(zhuǎn)換為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();
// 圖片編輯器基礎(chǔ)功能
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();
```
## 高級用法示例
### 響應(yīng)式圖片加載
```javascript
// 響應(yīng)式圖片Base64轉(zhuǎn)換
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;
}
```
### 圖片懶加載與透明度動(dòng)畫
```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 兼容性
- **現(xiàn)代瀏覽器**: 使用 `opacity` CSS屬性
- **IE 6-8**: 使用 `filter: alpha(opacity=n)`
- **完全兼容**: IE 6+ 及所有現(xiàn)代瀏覽器
### imageToBase64 兼容性
- **Canvas支持**: IE 9+ 及所有現(xiàn)代瀏覽器
- **圖片跨域**: 需要設(shè)置 `crossOrigin` 屬性
- **文件大小**: 受瀏覽器內(nèi)存限制
## 性能優(yōu)化建議
1. **圖片緩存**: 重復(fù)轉(zhuǎn)換的圖片應(yīng)該緩存Base64結(jié)果
2. **尺寸控制**: 大圖片轉(zhuǎn)換前先壓縮尺寸
3. **質(zhì)量平衡**: 根據(jù)使用場景選擇合適的圖片質(zhì)量
4. **內(nèi)存管理**: 及時(shí)清理不需要的Canvas元素
## 注意事項(xiàng)
1. **跨域問題**: 圖片轉(zhuǎn)Base64時(shí)注意跨域限制
2. **內(nèi)存占用**: Base64編碼會(huì)增加約33%的數(shù)據(jù)大小
3. **性能影響**: 大圖片處理會(huì)消耗較多CPU和內(nèi)存
4. **瀏覽器限制**: 某些瀏覽器對Base64長度有限制
## 錯(cuò)誤處理
```javascript
// 安全的圖片轉(zhuǎn)換
function safeImageToBase64(img) {
try {
if (!img || !img.naturalWidth) {
throw new Error('無效的圖片元素');
}
return sinma.imageToBase64(img);
} catch (error) {
console.error('圖片轉(zhuǎn)換失敗:', error);
return null;
}
}
// 安全的透明度設(shè)置
function safeSetOpacity(element, opacity) {
try {
if (!element || typeof opacity !== 'number') {
throw new Error('無效的參數(shù)');
}
if (opacity < 0 || opacity > 1) {
throw new Error('透明度值必須在0-1之間');
}
sinma.setOpacity(element, opacity);
} catch (error) {
console.error('設(shè)置透明度失敗:', error);
}
}
```
## 相關(guān)模塊
- [字符串模塊](./string.md) - 提供Base64字符串處理功能
- [工具函數(shù)模塊](./utils.md) - 提供類型檢查等輔助功能
- [數(shù)字模塊](./number.md) - 提供數(shù)值計(jì)算功能
