Π§ΡΠΎ ΠΌΡ ΡΠ΄Π΅Π»Π°Π»ΠΈ
ΠΠ°ΡΠ° ΠΌΠΈΡΡΠΈΡ β ΡΠΎΠ·Π΄Π°ΡΡ ΡΠΊΡΠΈΠΏΡ, ΠΊΠΎΡΠΎΡΡΠΉ ΡΠΌΠ΅Π΅Ρ:
- ΠΊΠΎΠ½Π²Π΅ΡΡΠΈΡΠΎΠ²Π°ΡΡ RAW-ΡΠ°ΠΉΠ»Ρ Π² ΠΎΠΏΡΠΈΠΌΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΡΠ΅ JPEG;
- ΠΊΠ°Π΄ΡΠΈΡΠΎΠ²Π°ΡΡ ΡΠΎΡΠΎΠ³ΡΠ°ΡΠΈΠΈ ΠΏΠΎ Π·Π°Π΄Π°Π½Π½ΡΠΌ ΠΏΡΠΎΠΏΠΎΡΡΠΈΡΠΌ;
- Π΄ΠΎΠ±Π°Π²Π»ΡΡΡ ΡΠ»Π΅Π³Π°Π½ΡΠ½ΡΠ΅ Π²ΠΎΠ΄ΡΠ½ΡΠ΅ Π·Π½Π°ΠΊΠΈ Ρ Π΄Π°ΡΠΎΠΉ ΠΈ ΠΈΠ½Π΄Π΅ΠΊΡΠ°ΡΠΈΠ΅ΠΉ;
- Π΄Π΅Π»Π°ΡΡ ΡΡΠΎ Π² Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠΌ ΡΠ΅ΠΆΠΈΠΌΠ΅ Π±Π΅Π· ΡΡΠ°ΡΡΠΈΡ ΡΠΎΡΠΎΠ³ΡΠ°ΡΠ°.
Π Π°Π±ΠΎΡΠΈΠΉ ΠΏΡΠΎΡΠΎΡΠΈΠΏ ΡΠΎΠ±ΡΠ°Π»ΠΈ Π·Π° 2 Π΄Π½Ρ. Π‘ΠΊΡΠΈΠΏΡ Π½Π° TypeScript + Node.js.
Π‘ΡΠ΅ΠΊ
- TypeScript β Π΄Π»Ρ ΡΠΈΠΏΠΎΠ±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΠΈ ΠΈ ΡΠ΄ΠΎΠ±ΡΡΠ²Π° ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ
- Node.js β ΠΎΡΠ½ΠΎΠ²Π° ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ
- fs-extra β ΡΠ°ΡΡΠΈΡΠ΅Π½Π½ΡΠΉ API Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ ΡΠ°ΠΉΠ»ΠΎΠ²ΠΎΠΉ ΡΠΈΡΡΠ΅ΠΌΠΎΠΉ
- canvas β Π΄Π»Ρ ΠΌΠ°Π½ΠΈΠΏΡΠ»ΡΡΠΈΠΈ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡΠΌΠΈ
- exif β ΠΈΠ·Π²Π»Π΅ΡΠ΅Π½ΠΈΠ΅ ΠΌΠ΅ΡΠ°Π΄Π°Π½Π½ΡΡ ΠΈΠ· ΡΠΎΡΠΎΠ³ΡΠ°ΡΠΈΠΉ
- sips β macOS-ΡΡΠΈΠ»ΠΈΡΠ° Π΄Π»Ρ Π±ΡΡΡΡΡΡ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΉ Ρ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡΠΌΠΈ
1. ΠΡΠ³Π°Π½ΠΈΠ·Π°ΡΠΈΡ ΠΏΡΠΎΡΠ΅ΡΡΠ° ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ
Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ ΡΡΠ½ΠΊΡΠΈΡ, ΡΠ΅Π°Π»ΠΈΠ·ΡΡΡΡΡ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΠ΅Π»ΡΠ½ΠΎΡΡΡ ΡΠ°Π³ΠΎΠ² ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ:
// ΠΡΠ½ΠΎΠ²Π½ΠΎΠΉ ΠΏΡΠΎΡΠ΅ΡΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ ΡΠΎΡΠΎΠ³ΡΠ°ΡΠΈΠΉ
export const preparePhotos = async (fromDirPath: string, toDirPath: string) => {
// Π‘ΠΎΠ·Π΄Π°ΡΠΌ Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΡ Π΄Π»Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠ°Π½Π½ΡΡ
ΡΠ°ΠΉΠ»ΠΎΠ²
await ensureDir(toDirPath);
// Π¨Π°Π³ 1: ΠΠΎΠ½Π²Π΅ΡΡΠ°ΡΠΈΡ Π² JPEG
await toJpg(fromDirPath, toDirPath);
console.log("ΠΠΎΠ½Π²Π΅ΡΡΠ°ΡΠΈΡ Π² JPEG Π·Π°Π²Π΅ΡΡΠ΅Π½Π°");
// Π¨Π°Π³ 2: ΠΠ°Π΄ΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠΉ
const croppedPath = path.join(toDirPath, "cropped");
await ensureDir(croppedPath);
await crop(toDirPath, croppedPath);
console.log("ΠΠ°Π΄ΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΎ");
// Π¨Π°Π³ 3: ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π²ΠΎΠ΄ΡΠ½ΡΡ
Π·Π½Π°ΠΊΠΎΠ²
const watermarkedPath = path.join(croppedPath, "watermarked");
await ensureDir(watermarkedPath);
await addWatermark(croppedPath, watermarkedPath);
console.log("ΠΠΎΠ΄ΡΠ½ΡΠ΅ Π·Π½Π°ΠΊΠΈ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Ρ");
};
2. ΠΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΡ ΡΠΎΡΠΌΠ°ΡΠΎΠ² ΠΈ ΡΠ½ΠΈΡΠΈΠΊΠ°ΡΠΈΡ
ΠΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ ΡΠΈΡΡΠ΅ΠΌΠ½ΡΡ ΡΡΠΈΠ»ΠΈΡΡ Π΄Π»Ρ Π±ΡΡΡΡΠΎΠΉ ΠΊΠΎΠ½Π²Π΅ΡΡΠ°ΡΠΈΠΈ Π²ΡΠ΅Ρ ΡΠΎΡΠΌΠ°ΡΠΎΠ² Π² JPEG:
// ΠΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΡΠ°ΠΉΠ»ΠΎΠ² Π² ΠΈΡΡ
ΠΎΠ΄Π½ΠΎΠΉ Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΠΈ
fs.readdir(fromDirPath, (err, files) => {
// ΠΠΎΠ΄Π³ΠΎΡΠΎΠ²ΠΊΠ° Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΠΈ Π΄Π»Ρ Π²ΡΡ
ΠΎΠ΄Π½ΡΡ
ΡΠ°ΠΉΠ»ΠΎΠ²
fs.mkdirSync(toDirPath, { recursive: true });
// ΠΠ°ΡΠ°Π»Π»Π΅Π»ΡΠ½Π°Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ° Π²ΡΠ΅Ρ
ΡΠ°ΠΉΠ»ΠΎΠ²
const convertPromises = files.map((file) => {
// Π€ΠΎΡΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΠΏΡΡΠ΅ΠΉ ΠΊ ΠΈΡΡ
ΠΎΠ΄Π½ΠΈΠΊΡ ΠΈ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΡ
const filePath = path.join(fromDirPath, file);
const outputFilePath = path.join(
toDirPath,
path.parse(file).name + `.${JPEG_EXTENSION}`
);
// ΠΡΠΈΠ½Ρ
ΡΠΎΠ½Π½ΡΠΉ Π·Π°ΠΏΡΡΠΊ ΠΊΠΎΠ½Π²Π΅ΡΡΠ°ΡΠΈΠΈ
return new Promise((resolve, reject) => {
exec(`sips -s format ${JPEG_EXTENSION} "${filePath}" --out "${outputFilePath}"`,
(error) => {
if (error) reject(error);
else resolve("Π€Π°ΠΉΠ» ΠΊΠΎΠ½Π²Π΅ΡΡΠΈΡΠΎΠ²Π°Π½");
});
});
});
3. ΠΠ½ΡΠ΅Π»Π»Π΅ΠΊΡΡΠ°Π»ΡΠ½ΠΎΠ΅ ΠΊΠ°Π΄ΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΠΏΠΎΠ΄ Π·Π°Π΄Π°Π½Π½ΡΠ΅ ΠΏΡΠΎΠΏΠΎΡΡΠΈΠΈ
ΠΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π΅ΠΌ ΠΊΠ°ΠΆΠ΄ΠΎΠ΅ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅ Ρ ΡΡΠ΅ΡΠΎΠΌ Π΅Π³ΠΎ ΠΎΡΠΈΠ΅Π½ΡΠ°ΡΠΈΠΈ ΠΈ ΡΡΠ΅Π±ΡΠ΅ΠΌΡΡ ΠΏΡΠΎΠΏΠΎΡΡΠΈΠΉ:
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° ΡΠ΅Π»Π΅Π²ΠΎΠ³ΠΎ ΡΠΎΠΎΡΠ½ΠΎΡΠ΅Π½ΠΈΡ ΡΡΠΎΡΠΎΠ½
const aspectRatio = { x: 10, y: 15 };
// ΠΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΡΠΏΠΈΡΠΊΠ° ΡΠ°ΠΉΠ»ΠΎΠ² Π΄Π»Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ
const files = fs.readdirSync(fromDirPath);
// ΠΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΡΠ°ΠΉΠ»ΠΎΠ² ΠΏΠΎ ΠΎΠ΄Π½ΠΎΠΌΡ
files.forEach((file, index) => {
// ΠΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΡΠ°Π·ΠΌΠ΅ΡΠΎΠ² ΠΈΡΡ
ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡ
const imgWidth = parseInt(
execSync(`sips -g pixelWidth "${filePath}"`)
.toString()
.split(":")[1]
.trim()
);
// ΠΠ½Π°Π»ΠΎΠ³ΠΈΡΠ½ΠΎΠ΅ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π²ΡΡΠΎΡΡ
const imgHeight = /* ΠΊΠΎΠ΄ Π΄Π»Ρ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡ Π²ΡΡΠΎΡΡ */;
// ΠΠ΄Π°ΠΏΡΠ°ΡΠΈΡ ΡΠΎΠΎΡΠ½ΠΎΡΠ΅Π½ΠΈΡ ΠΏΠΎΠ΄ ΠΎΡΠΈΠ΅Π½ΡΠ°ΡΠΈΡ ΡΠ½ΠΈΠΌΠΊΠ°
let aspectRatioX = aspectRatio.x;
let aspectRatioY = aspectRatio.y;
if (imgWidth > imgHeight) {
// ΠΠ½Π²Π΅ΡΡΠΈΡ ΡΠΎΠΎΡΠ½ΠΎΡΠ΅Π½ΠΈΡ Π΄Π»Ρ Π³ΠΎΡΠΈΠ·ΠΎΠ½ΡΠ°Π»ΡΠ½ΡΡ
ΡΠΎΡΠΎ
[aspectRatioX, aspectRatioY] = [aspectRatioY, aspectRatioX];
}
// ΠΠΎΠΏΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠ°ΠΉΠ»Π° Π΄Π»Ρ ΠΏΠΎΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΉ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ
fs.copyFileSync(filePath, destFilePath);
// ΠΡΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ ΠΊΠ°Π΄ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ Ρ Π½ΠΎΠ²ΡΠΌΠΈ ΡΠ°Π·ΠΌΠ΅ΡΠ°ΠΌΠΈ
execSync(`sips --cropToHeightWidth ${newHeight} ${newWidth} "${destFilePath}"`);
console.log(`Π€Π°ΠΉΠ» ΠΎΠ±ΡΠ°Π±ΠΎΡΠ°Π½: ${file}. ΠΡΠΎΠ³ΡΠ΅ΡΡ: ${index + 1}/${files.length}`);
});
4. ΠΠ΅ΡΡΠΎΠ½Π°Π»ΠΈΠ·Π°ΡΠΈΡ Π²ΠΎΠ΄ΡΠ½ΡΡ Π·Π½Π°ΠΊΠΎΠ² Ρ ΠΌΠ΅ΡΠ°Π΄Π°Π½Π½ΡΠΌΠΈ
ΠΠΎΠ±Π°Π²Π»ΡΠ΅ΠΌ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠ²Π½ΡΠ΅ ΠΈ ΡΡΠΈΠ»ΡΠ½ΡΠ΅ Π²ΠΎΠ΄ΡΠ½ΡΠ΅ Π·Π½Π°ΠΊΠΈ Ρ ΠΈΠ·Π²Π»Π΅ΡΠ΅Π½ΠΈΠ΅ΠΌ Π΄Π°ΡΡ ΠΈΠ· EXIF:
// ΠΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡ
fs.readdir(fromDirPath, async (err, files: string[]) => {
for (const file of files) {
// ΠΠ·Π²Π»Π΅ΡΠ΅Π½ΠΈΠ΅ EXIF-ΠΌΠ΅ΡΠ°Π΄Π°Π½Π½ΡΡ
new ExifImage({ image: filePath }, async (error, exifData: ExifData) => {
// ΠΠΎΠ΄Π³ΠΎΡΠΎΠ²ΠΊΠ° ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡ ΠΊ ΡΠ΅Π΄Π°ΠΊΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ
const image = await loadImage(filePath);
const canvas = createCanvas(image.width, image.height);
const ctx = canvas.getContext("2d");
// Π Π°Π·ΠΌΠ΅ΡΠ΅Π½ΠΈΠ΅ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡ Π½Π° Ρ
ΠΎΠ»ΡΡΠ΅
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
// ΠΠ·Π²Π»Π΅ΡΠ΅Π½ΠΈΠ΅ Π΄Π°ΡΡ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΠΈΠ· ΠΌΠ΅ΡΠ°Π΄Π°Π½Π½ΡΡ
let dateCreated;
if (exifData?.exif?.CreateDate) {
dateCreated = exifData.exif.CreateDate
.replace(":", "-")
.replace(":", "-");
}
// ΠΠΎΠ΄Π³ΠΎΡΠΎΠ²ΠΊΠ° ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠΈ Π΄Π»Ρ Π²ΠΎΠ΄ΡΠ½ΠΎΠ³ΠΎ Π·Π½Π°ΠΊΠ°
const photoCaption = path.parse(file).name;
// ΠΡΠΎΠ²Π΅ΡΠΊΠ° Π½Π°Π»ΠΈΡΠΈΡ ΡΠΏΡΠ°Π²Π»ΡΡΡΠΈΡ
ΠΌΠ΅ΡΠΎΠΊ Π² ΠΈΠΌΠ΅Π½ΠΈ ΡΠ°ΠΉΠ»Π°
const skipWatermark = photoCaption.includes("nowm");
const partialName = photoCaption.includes("name")
? photoCaption.split("name")[0]
: photoCaption;
// ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π²ΠΎΠ΄ΡΠ½ΠΎΠ³ΠΎ Π·Π½Π°ΠΊΠ° ΠΏΡΠΈ Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΠΎΡΡΠΈ
if (partialName && !skipWatermark) {
writeText(
ctx,
`${partialName}${
dateCreated ? ` β’ ${dateCreated}` : ""
}`,
35, // ΠΎΡΡΡΡΠΏ ΠΏΠΎ Π³ΠΎΡΠΈΠ·ΠΎΠ½ΡΠ°Π»ΠΈ
75 // ΠΏΠΎΠ·ΠΈΡΠΈΡ ΠΏΠΎ Π²Π΅ΡΡΠΈΠΊΠ°Π»ΠΈ
);
}
// Π‘ΠΎΡ
ΡΠ°Π½Π΅Π½ΠΈΠ΅ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠ° Π² ΡΠ°ΠΉΠ»
const out = fs.createWriteStream(destFilePath);
const stream = canvas.createJPEGStream({
quality: 0.95,
progressive: true
});
stream.pipe(out);
out.on("finish", () => {
console.log(`ΠΠ±ΡΠ°Π±ΠΎΡΠ°Π½ ΡΠ°ΠΉΠ»: ${file}`);
});
});
}
});
// Π€ΡΠ½ΠΊΡΠΈΡ Π΄Π»Ρ ΠΎΡΡΠΈΡΠΎΠ²ΠΊΠΈ ΡΠ΅ΠΊΡΡΠΎΠ²ΠΎΠ³ΠΎ Π²ΠΎΠ΄ΡΠ½ΠΎΠ³ΠΎ Π·Π½Π°ΠΊΠ°
function writeText(ctx, text, x, y) {
// ΠΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ ΡΠ°Π·ΠΌΠ΅ΡΠΎΠ² ΡΠ΅ΠΊΡΡΠ°
const textWidth = ctx.measureText(text).width;
// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΡΠΎΠ½Π° Π΄Π»Ρ ΡΠ΅ΠΊΡΡΠ°
ctx.fillStyle = "rgba(0, 0, 0, 0.5)";
ctx.fillRect(0, y - 75, textWidth + 70, 100);
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° ΡΡΠΈΠ»Ρ ΠΈ ΠΎΡΡΠΈΡΠΎΠ²ΠΊΠ° ΡΠ΅ΠΊΡΡΠ°
ctx.font = "24px Helvetica";
ctx.fillStyle = "white";
ctx.strokeStyle = "black";
ctx.lineWidth = 1;
ctx.strokeText(text, x, y);
ctx.fillText(text, x, y);
}
β Π§ΡΠΎ Π² ΠΈΡΠΎΠ³Π΅ ΠΏΠΎΠ»ΡΡΠΈΠ» ΠΊΠ»ΠΈΠ΅Π½Ρ
- Π‘ΠΎΠΊΡΠ°ΡΠ΅Π½ΠΈΠ΅ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ Ρ 8 ΡΠ°ΡΠΎΠ² Π΄ΠΎ 15 ΠΌΠΈΠ½ΡΡ Π½Π° ΡΠΎΡΠΎΡΠ΅ΡΡΠΈΡ
- Π£Π½ΠΈΡΠΈΡΠΈΡΠΎΠ²Π°Π½Π½ΡΠΉ ΡΡΠΈΠ»Ρ Π²ΡΠ΅Ρ ΡΠΎΡΠΎΠ³ΡΠ°ΡΠΈΠΉ Π² ΠΏΡΠΎΠ΅ΠΊΡΠ΅
- ΠΠ²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠ°Ρ Π±ΡΠ΅Π½Π΄ΠΈΡΠΎΠ²Π°Π½Π½Π°Ρ ΠΌΠ°ΡΠΊΠΈΡΠΎΠ²ΠΊΠ° ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠΉ
- ΠΠΏΡΠΈΠΌΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΡΠ΅ ΡΠΎΡΠΌΠ°ΡΡ, Π³ΠΎΡΠΎΠ²ΡΠ΅ Π΄Π»Ρ ΠΏΠ΅ΡΠ°ΡΠΈ ΠΈΠ»ΠΈ ΠΏΡΠ±Π»ΠΈΠΊΠ°ΡΠΈΠΈ
- ΠΠΊΠΎΠ½ΠΎΠΌΠΈΡ ΠΎΠΊΠΎΠ»ΠΎ 40 ΡΡΡΡΡ ΡΡΠ±Π»Π΅ΠΉ Π΅ΠΆΠ΅ΠΌΠ΅ΡΡΡΠ½ΠΎ Π½Π° ΠΏΠΎΡΡΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ΅
Π§ΡΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΡΠ»ΡΡΡΠΈΡΡ
- ΠΠ½Π΅Π΄ΡΠΈΡΡ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΡΡ ΡΠ²Π΅ΡΠΎΠΊΠΎΡΡΠ΅ΠΊΡΠΈΡ ΠΈ ΡΠΎΠ½Π°Π»ΡΠ½ΡΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΡ
- ΠΠΎΠ±Π°Π²ΠΈΡΡ ΡΠ°ΡΠΏΠΎΠ·Π½Π°Π²Π°Π½ΠΈΠ΅ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² Π΄Π»Ρ ΡΠΌΠ½ΠΎΠ³ΠΎ ΠΊΠ°Π΄ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ
- Π Π°Π·ΡΠ°Π±ΠΎΡΠ°ΡΡ Π³ΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠΉ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ Π½Π° Electron Π΄Π»Ρ ΡΠΎΡΠΎΠ³ΡΠ°ΡΠΎΠ²
- Π‘ΠΎΠ·Π΄Π°Π²Π°ΡΡ Π½Π°Π±ΠΎΡΡ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠΉ ΡΠ°Π·Π½ΡΡ ΡΠ°Π·ΠΌΠ΅ΡΠΎΠ² Π΄Π»Ρ ΡΠ°Π·Π½ΡΡ ΠΏΠ»Π°ΡΡΠΎΡΠΌ
- ΠΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ Ρ ΡΠ΅ΡΠ²ΠΈΡΠ°ΠΌΠΈ ΠΏΠ΅ΡΠ°ΡΠΈ ΠΈ ΠΏΡΠ±Π»ΠΈΠΊΠ°ΡΠΈΠΈ Π°Π»ΡΠ±ΠΎΠΌΠΎΠ²
Π£ Π²Π°Ρ Π΅ΡΡΡ ΡΠ²ΠΎΡΡΠ΅ΡΠΊΠΈΠ΅ ΠΏΡΠΎΡΠ΅ΡΡΡ, ΡΡΠ΅Π±ΡΡΡΠΈΠ΅ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΠ·Π°ΡΠΈΠΈ?
ΠΠ°ΠΏΠΈΡΠΈΡΠ΅ Π½Π°ΠΌ β ΠΏΡΠ΅Π²ΡΠ°ΡΠΈΠΌ ΡΡΡΠΈΠ½Π½ΡΠ΅ Π·Π°Π΄Π°ΡΠΈ Π² ΠΎΠ΄ΠΈΠ½ ΠΊΠ»ΠΈΠΊ, ΠΎΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Ρ Π²ΡΠ΅ΠΌΡ Π΄Π»Ρ Π΄Π΅ΠΉΡΡΠ²ΠΈΡΠ΅Π»ΡΠ½ΠΎ Π²Π°ΠΆΠ½ΠΎΠΉ ΡΠ°Π±ΠΎΡΡ.