@adstage/web-sdk 2.1.2 โ 2.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.js +364 -22
- package/dist/index.d.ts +40 -0
- package/dist/index.esm.js +364 -22
- package/dist/index.standalone.js +364 -22
- package/package.json +1 -1
- package/src/modules/ads/AdsModule.ts +427 -22
package/dist/index.standalone.js
CHANGED
|
@@ -2052,7 +2052,7 @@ class AdsModule {
|
|
|
2052
2052
|
this.ensureReady();
|
|
2053
2053
|
const adstageOptions = {
|
|
2054
2054
|
width: options?.width || '100%',
|
|
2055
|
-
height: options?.height ||
|
|
2055
|
+
height: options?.height || 'auto', // ๐ง ๋์ ํฌ๊ธฐ ์กฐ์ ํ์ฉ
|
|
2056
2056
|
autoSlide: options?.autoSlide || false,
|
|
2057
2057
|
slideInterval: options?.slideInterval || 5000,
|
|
2058
2058
|
onClick: options?.onClick,
|
|
@@ -2219,8 +2219,10 @@ class AdsModule {
|
|
|
2219
2219
|
adElement.setAttribute('data-adstage-container', 'true');
|
|
2220
2220
|
adElement.setAttribute('data-adstage-type', type);
|
|
2221
2221
|
adElement.setAttribute('data-adstage-slot', slotId);
|
|
2222
|
-
|
|
2223
|
-
|
|
2222
|
+
// ์ค๋งํธํ ํฌ๊ธฐ ์ค์
|
|
2223
|
+
const { width, height } = this.calculateAdSize(container, type, options);
|
|
2224
|
+
adElement.style.width = width;
|
|
2225
|
+
adElement.style.height = height;
|
|
2224
2226
|
adElement.style.border = '1px dashed #ccc';
|
|
2225
2227
|
adElement.style.display = 'flex';
|
|
2226
2228
|
adElement.style.alignItems = 'center';
|
|
@@ -2230,7 +2232,267 @@ class AdsModule {
|
|
|
2230
2232
|
adElement.innerHTML = `<span>Loading ${type} ad...</span>`;
|
|
2231
2233
|
container.appendChild(adElement);
|
|
2232
2234
|
if (this._config?.debug) {
|
|
2233
|
-
console.log(`๐ฆ Placeholder created for slot: ${slotId}`);
|
|
2235
|
+
console.log(`๐ฆ Placeholder created for slot: ${slotId} (${width} x ${height})`);
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
/**
|
|
2239
|
+
* ์ปจํ
์ด๋์ ๊ด๊ณ ํ์
์ ๋ฐ๋ฅธ ์ค๋งํธํ ํฌ๊ธฐ ๊ณ์ฐ
|
|
2240
|
+
*/
|
|
2241
|
+
calculateAdSize(container, type, options) {
|
|
2242
|
+
// ์ฌ์ฉ์๊ฐ ๋ช
์์ ์ผ๋ก ํฌ๊ธฐ๋ฅผ ์ง์ ํ ๊ฒฝ์ฐ
|
|
2243
|
+
const explicitWidth = options.width;
|
|
2244
|
+
const explicitHeight = options.height;
|
|
2245
|
+
// ๋๋น ์ฒ๋ฆฌ
|
|
2246
|
+
let width;
|
|
2247
|
+
if (typeof explicitWidth === 'number') {
|
|
2248
|
+
width = `${explicitWidth}px`;
|
|
2249
|
+
}
|
|
2250
|
+
else if (typeof explicitWidth === 'string') {
|
|
2251
|
+
width = explicitWidth;
|
|
2252
|
+
}
|
|
2253
|
+
else {
|
|
2254
|
+
width = '100%'; // ๊ธฐ๋ณธ๊ฐ์ 100%
|
|
2255
|
+
}
|
|
2256
|
+
// ๋์ด ์ฒ๋ฆฌ - ํต์ฌ ๋ก์ง
|
|
2257
|
+
let height;
|
|
2258
|
+
if (typeof explicitHeight === 'number') {
|
|
2259
|
+
height = `${explicitHeight}px`;
|
|
2260
|
+
}
|
|
2261
|
+
else if (typeof explicitHeight === 'string' && explicitHeight !== '100%' && explicitHeight !== 'auto') {
|
|
2262
|
+
// ๋ช
์์ ์ธ ํฌ๊ธฐ ๋ฌธ์์ด (์: '200px', '50vh' ๋ฑ)
|
|
2263
|
+
height = explicitHeight;
|
|
2264
|
+
}
|
|
2265
|
+
else {
|
|
2266
|
+
// 100%, auto์ด๊ฑฐ๋ ๋์ด๊ฐ ์ง์ ๋์ง ์์ ๊ฒฝ์ฐ ์ค๋งํธ ๊ณ์ฐ
|
|
2267
|
+
const containerHeight = this.getContainerHeight(container);
|
|
2268
|
+
if (containerHeight > 0) {
|
|
2269
|
+
// ์ปจํ
์ด๋์ ๋์ด๊ฐ ์์ผ๋ฉด 100% ์ฌ์ฉ
|
|
2270
|
+
height = '100%';
|
|
2271
|
+
if (this._config?.debug) {
|
|
2272
|
+
console.log(`๐ Using 100% height (container: ${containerHeight}px)`);
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2275
|
+
else {
|
|
2276
|
+
// ์ปจํ
์ด๋์ ๋์ด๊ฐ ์์ผ๋ฉด ํ์
๋ณ ๊ธฐ๋ณธ๊ฐ ์ฌ์ฉ (๋์ค์ ๋์ ์กฐ์ ๋จ)
|
|
2277
|
+
height = this.getDefaultHeightForAdType(type);
|
|
2278
|
+
if (this._config?.debug) {
|
|
2279
|
+
console.log(`๐ Using default height ${height} (will be optimized for ${type})`);
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
}
|
|
2283
|
+
return { width, height };
|
|
2284
|
+
}
|
|
2285
|
+
/**
|
|
2286
|
+
* ์ปจํ
์ด๋์ ์ค์ ๋์ด ๊ณ์ฐ
|
|
2287
|
+
*/
|
|
2288
|
+
getContainerHeight(container) {
|
|
2289
|
+
// ํ์ฌ ๊ณ์ฐ๋ ์คํ์ผ์์ ๋์ด ํ์ธ
|
|
2290
|
+
const computedStyle = window.getComputedStyle(container);
|
|
2291
|
+
const height = parseFloat(computedStyle.height);
|
|
2292
|
+
// height๊ฐ auto์ด๊ฑฐ๋ 0์ด๋ฉด ๋ค๋ฅธ ๋ฐฉ๋ฒ๋ค ์๋
|
|
2293
|
+
if (!height || height === 0) {
|
|
2294
|
+
// min-height ํ์ธ
|
|
2295
|
+
const minHeight = parseFloat(computedStyle.minHeight);
|
|
2296
|
+
if (minHeight > 0)
|
|
2297
|
+
return minHeight;
|
|
2298
|
+
// CSS๋ก ์ค์ ๋ ๊ณ ์ ๋์ด ํ์ธ
|
|
2299
|
+
if (container.style.height && container.style.height !== 'auto') {
|
|
2300
|
+
const styleHeight = parseFloat(container.style.height);
|
|
2301
|
+
if (styleHeight > 0)
|
|
2302
|
+
return styleHeight;
|
|
2303
|
+
}
|
|
2304
|
+
// ์์ฑ์ผ๋ก ์ค์ ๋ ๋์ด ํ์ธ
|
|
2305
|
+
const heightAttr = container.getAttribute('height');
|
|
2306
|
+
if (heightAttr) {
|
|
2307
|
+
const attrHeight = parseFloat(heightAttr);
|
|
2308
|
+
if (attrHeight > 0)
|
|
2309
|
+
return attrHeight;
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
return height || 0;
|
|
2313
|
+
}
|
|
2314
|
+
/**
|
|
2315
|
+
* ๊ด๊ณ ํ์
๋ณ ๊ธฐ๋ณธ ๋์ด ๋ฐํ
|
|
2316
|
+
*/
|
|
2317
|
+
getDefaultHeightForAdType(type) {
|
|
2318
|
+
switch (type) {
|
|
2319
|
+
case AdType.BANNER:
|
|
2320
|
+
return '250px'; // ์ผ๋ฐ ๋ฐฐ๋
|
|
2321
|
+
case AdType.TEXT:
|
|
2322
|
+
return '120px'; // ํ
์คํธ๋ ์ข ๋ ์๊ฒ
|
|
2323
|
+
case AdType.VIDEO:
|
|
2324
|
+
return '360px'; // ๋น๋์ค๋ 16:9 ๋น์จ ๊ณ ๋ ค
|
|
2325
|
+
case AdType.NATIVE:
|
|
2326
|
+
return '200px'; // ๋ค์ดํฐ๋ธ๋ ์ค๊ฐ ํฌ๊ธฐ
|
|
2327
|
+
case AdType.INTERSTITIAL:
|
|
2328
|
+
return '400px'; // ์ ๋ฉด๊ด๊ณ ๋ ํฌ๊ฒ
|
|
2329
|
+
default:
|
|
2330
|
+
return '250px';
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
/**
|
|
2334
|
+
* ์ด๋ฏธ์ง ํฌ๊ธฐ ์ ๋ณด ๋ก๋ (ํ๋ฆฌ๋ก๋ฉ)
|
|
2335
|
+
*/
|
|
2336
|
+
async loadImageDimensions(imageUrl) {
|
|
2337
|
+
return new Promise((resolve, reject) => {
|
|
2338
|
+
const img = new Image();
|
|
2339
|
+
img.onload = () => {
|
|
2340
|
+
resolve({ width: img.naturalWidth, height: img.naturalHeight });
|
|
2341
|
+
};
|
|
2342
|
+
img.onerror = () => {
|
|
2343
|
+
reject(new Error(`Failed to load image: ${imageUrl}`));
|
|
2344
|
+
};
|
|
2345
|
+
img.src = imageUrl;
|
|
2346
|
+
});
|
|
2347
|
+
}
|
|
2348
|
+
/**
|
|
2349
|
+
* ์ฌ๋ฌ ๊ด๊ณ ์ ์ต์ ์ปจํ
์ด๋ ํฌ๊ธฐ ๊ณ์ฐ (๋์ ํฌ๊ธฐ ์กฐ์ )
|
|
2350
|
+
*/
|
|
2351
|
+
async calculateOptimalContainerSize(advertisements, containerWidth, adType) {
|
|
2352
|
+
if (!advertisements.length || adType !== AdType.BANNER) {
|
|
2353
|
+
// ๋ฐฐ๋๊ฐ ์๋๊ฑฐ๋ ๊ด๊ณ ๊ฐ ์์ผ๋ฉด ๊ธฐ๋ณธ๊ฐ
|
|
2354
|
+
return {
|
|
2355
|
+
width: '100%',
|
|
2356
|
+
height: this.getDefaultHeightForAdType(adType),
|
|
2357
|
+
aspectRatio: 16 / 9
|
|
2358
|
+
};
|
|
2359
|
+
}
|
|
2360
|
+
try {
|
|
2361
|
+
// ๋ชจ๋ ๋ฐฐ๋ ์ด๋ฏธ์ง์ ํฌ๊ธฐ ์ ๋ณด ๋ก๋
|
|
2362
|
+
const imageDimensions = await Promise.allSettled(advertisements
|
|
2363
|
+
.filter(ad => ad.imageUrl)
|
|
2364
|
+
.map(ad => this.loadImageDimensions(ad.imageUrl)));
|
|
2365
|
+
const validDimensions = imageDimensions
|
|
2366
|
+
.filter((result) => result.status === 'fulfilled')
|
|
2367
|
+
.map(result => result.value);
|
|
2368
|
+
if (validDimensions.length === 0) {
|
|
2369
|
+
// ์ด๋ฏธ์ง ๋ก๋ ์คํจ์ ๊ธฐ๋ณธ๊ฐ
|
|
2370
|
+
return {
|
|
2371
|
+
width: '100%',
|
|
2372
|
+
height: this.getDefaultHeightForAdType(adType),
|
|
2373
|
+
aspectRatio: 16 / 9
|
|
2374
|
+
};
|
|
2375
|
+
}
|
|
2376
|
+
// ์ต์ ์ ๋ต ์ ํ
|
|
2377
|
+
const strategy = this.selectOptimalSizeStrategy(validDimensions);
|
|
2378
|
+
const optimalHeight = this.calculateOptimalHeight(validDimensions, containerWidth, strategy);
|
|
2379
|
+
if (this._config?.debug) {
|
|
2380
|
+
console.log(`๐ Optimal container calculated: ${containerWidth}x${optimalHeight} (strategy: ${strategy})`);
|
|
2381
|
+
}
|
|
2382
|
+
return {
|
|
2383
|
+
width: '100%',
|
|
2384
|
+
height: `${optimalHeight}px`,
|
|
2385
|
+
aspectRatio: containerWidth / optimalHeight
|
|
2386
|
+
};
|
|
2387
|
+
}
|
|
2388
|
+
catch (error) {
|
|
2389
|
+
console.warn('Failed to calculate optimal size, using defaults:', error);
|
|
2390
|
+
return {
|
|
2391
|
+
width: '100%',
|
|
2392
|
+
height: this.getDefaultHeightForAdType(adType),
|
|
2393
|
+
aspectRatio: 16 / 9
|
|
2394
|
+
};
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
/**
|
|
2398
|
+
* ์ต์ ํฌ๊ธฐ ์กฐ์ ์ ๋ต ์ ํ
|
|
2399
|
+
*/
|
|
2400
|
+
selectOptimalSizeStrategy(dimensions) {
|
|
2401
|
+
const aspectRatios = dimensions.map(d => d.width / d.height);
|
|
2402
|
+
// 1. ๊ณตํต ๋น์จ์ด ์๋์ง ํ์ธ (ยฑ0.1 ํ์ฉ)
|
|
2403
|
+
const ratioGroups = new Map();
|
|
2404
|
+
aspectRatios.forEach(ratio => {
|
|
2405
|
+
const roundedRatio = Math.round(ratio * 10) / 10;
|
|
2406
|
+
const key = roundedRatio.toString();
|
|
2407
|
+
ratioGroups.set(key, (ratioGroups.get(key) || 0) + 1);
|
|
2408
|
+
});
|
|
2409
|
+
const maxGroup = Math.max(...ratioGroups.values());
|
|
2410
|
+
const totalImages = dimensions.length;
|
|
2411
|
+
// 70% ์ด์์ด ๋น์ทํ ๋น์จ์ด๋ฉด dominant ์ ๋ต
|
|
2412
|
+
if (maxGroup / totalImages >= 0.7) {
|
|
2413
|
+
return 'dominant';
|
|
2414
|
+
}
|
|
2415
|
+
// ํ์ค ๋น์จ๋ค์ด ๋ง์ผ๋ฉด common ์ ๋ต
|
|
2416
|
+
const standardRatios = [16 / 9, 4 / 3, 1 / 1, 3 / 2];
|
|
2417
|
+
const standardCount = aspectRatios.filter(ratio => standardRatios.some(standard => Math.abs(ratio - standard) < 0.1)).length;
|
|
2418
|
+
if (standardCount / totalImages >= 0.5) {
|
|
2419
|
+
return 'common';
|
|
2420
|
+
}
|
|
2421
|
+
// ๊ธฐ๋ณธ์ ํ๊ท ์ ๋ต
|
|
2422
|
+
return 'average';
|
|
2423
|
+
}
|
|
2424
|
+
/**
|
|
2425
|
+
* ์ ๋ต์ ๋ฐ๋ฅธ ์ต์ ๋์ด ๊ณ์ฐ
|
|
2426
|
+
*/
|
|
2427
|
+
calculateOptimalHeight(dimensions, containerWidth, strategy) {
|
|
2428
|
+
const aspectRatios = dimensions.map(d => d.width / d.height);
|
|
2429
|
+
switch (strategy) {
|
|
2430
|
+
case 'dominant':
|
|
2431
|
+
// ๊ฐ์ฅ ๋ง์ ๋น์จ์ ๊ธฐ์ค์ผ๋ก
|
|
2432
|
+
const ratioGroups = new Map();
|
|
2433
|
+
aspectRatios.forEach(ratio => {
|
|
2434
|
+
const roundedRatio = Math.round(ratio * 10) / 10;
|
|
2435
|
+
const key = roundedRatio.toString();
|
|
2436
|
+
const existing = ratioGroups.get(key);
|
|
2437
|
+
if (existing) {
|
|
2438
|
+
existing.count++;
|
|
2439
|
+
}
|
|
2440
|
+
else {
|
|
2441
|
+
ratioGroups.set(key, { ratio: roundedRatio, count: 1 });
|
|
2442
|
+
}
|
|
2443
|
+
});
|
|
2444
|
+
const dominantGroup = Array.from(ratioGroups.values())
|
|
2445
|
+
.reduce((max, current) => current.count > max.count ? current : max);
|
|
2446
|
+
return Math.round(containerWidth / dominantGroup.ratio);
|
|
2447
|
+
case 'common':
|
|
2448
|
+
// ํ์ค ๋น์จ ์ค ๊ฐ์ฅ ์ ํฉํ ๊ฒ ์ ํ
|
|
2449
|
+
const standardRatios = [
|
|
2450
|
+
{ ratio: 16 / 9, name: '16:9' },
|
|
2451
|
+
{ ratio: 4 / 3, name: '4:3' },
|
|
2452
|
+
{ ratio: 1 / 1, name: '1:1' },
|
|
2453
|
+
{ ratio: 3 / 2, name: '3:2' }
|
|
2454
|
+
];
|
|
2455
|
+
const avgRatio = aspectRatios.reduce((sum, ratio) => sum + ratio, 0) / aspectRatios.length;
|
|
2456
|
+
const bestStandard = standardRatios.reduce((best, current) => Math.abs(current.ratio - avgRatio) < Math.abs(best.ratio - avgRatio) ? current : best);
|
|
2457
|
+
if (this._config?.debug) {
|
|
2458
|
+
console.log(`๐ Using standard ratio: ${bestStandard.name} (avg: ${avgRatio.toFixed(2)})`);
|
|
2459
|
+
}
|
|
2460
|
+
return Math.round(containerWidth / bestStandard.ratio);
|
|
2461
|
+
case 'average':
|
|
2462
|
+
default:
|
|
2463
|
+
// ํ๊ท ๋น์จ ์ฌ์ฉ
|
|
2464
|
+
const averageRatio = aspectRatios.reduce((sum, ratio) => sum + ratio, 0) / aspectRatios.length;
|
|
2465
|
+
return Math.round(containerWidth / averageRatio);
|
|
2466
|
+
}
|
|
2467
|
+
}
|
|
2468
|
+
/**
|
|
2469
|
+
* ๊ฐ๋ณ ์ด๋ฏธ์ง์ ์ต์ ํ๋ ๋ ๋๋ง ์คํ์ผ ์ ์ฉ
|
|
2470
|
+
*/
|
|
2471
|
+
applyOptimizedImageStyle(img, imageAspectRatio, containerAspectRatio) {
|
|
2472
|
+
const ratio = imageAspectRatio / containerAspectRatio;
|
|
2473
|
+
if (Math.abs(ratio - 1) < 0.1) {
|
|
2474
|
+
// ๋น์จ์ด ๊ฑฐ์ ๊ฐ์ผ๋ฉด cover ์ฌ์ฉ
|
|
2475
|
+
img.style.objectFit = 'cover';
|
|
2476
|
+
img.style.objectPosition = 'center';
|
|
2477
|
+
}
|
|
2478
|
+
else if (ratio > 1.3) {
|
|
2479
|
+
// ์ด๋ฏธ์ง๊ฐ ํจ์ฌ ๊ฐ๋กํ์ด๋ฉด contain์ผ๋ก ์ ์ฒด ๋ณด์ด๊ธฐ
|
|
2480
|
+
img.style.objectFit = 'contain';
|
|
2481
|
+
img.style.objectPosition = 'center';
|
|
2482
|
+
img.style.backgroundColor = '#f0f0f0'; // ๋น ๊ณต๊ฐ ๋ฐฐ๊ฒฝ์
|
|
2483
|
+
}
|
|
2484
|
+
else if (ratio < 0.7) {
|
|
2485
|
+
// ์ด๋ฏธ์ง๊ฐ ํจ์ฌ ์ธ๋กํ์ด๋ฉด cover๋ก ์ฑ์ฐ๊ธฐ
|
|
2486
|
+
img.style.objectFit = 'cover';
|
|
2487
|
+
img.style.objectPosition = 'center';
|
|
2488
|
+
}
|
|
2489
|
+
else {
|
|
2490
|
+
// ์ ๋นํ ์ฐจ์ด๋ฉด ์ค๋งํธ cover
|
|
2491
|
+
img.style.objectFit = 'cover';
|
|
2492
|
+
img.style.objectPosition = 'center';
|
|
2493
|
+
}
|
|
2494
|
+
if (this._config?.debug) {
|
|
2495
|
+
console.log(`๐จ Image style applied: objectFit=${img.style.objectFit}, ratio=${ratio.toFixed(2)}`);
|
|
2234
2496
|
}
|
|
2235
2497
|
}
|
|
2236
2498
|
/**
|
|
@@ -2244,6 +2506,10 @@ class AdsModule {
|
|
|
2244
2506
|
this.renderFallback(slot);
|
|
2245
2507
|
return;
|
|
2246
2508
|
}
|
|
2509
|
+
// ๐ ๋์ ํฌ๊ธฐ ์กฐ์ : ๋ฐฐ๋ ๊ด๊ณ ์ ๊ฒฝ์ฐ ์ด๋ฏธ์ง ํฌ๊ธฐ ๊ธฐ๋ฐ์ผ๋ก ์ปจํ
์ด๋ ์ต์ ํ
|
|
2510
|
+
if (slot.adType === AdType.BANNER && adstageData.length > 0) {
|
|
2511
|
+
await this.optimizeContainerForBannerAds(slot, adstageData);
|
|
2512
|
+
}
|
|
2247
2513
|
// ๊ด๊ณ ๊ฐ ์ฌ๋ฌ ๊ฐ์ด๊ฑฐ๋ autoSlide ์ต์
์ด ์์ผ๋ฉด ์ฌ๋ผ์ด๋๋ก ๋ ๋๋ง
|
|
2248
2514
|
if (adstageData.length > 1 || slot.config?.autoSlide) {
|
|
2249
2515
|
await this.renderAdSlider(slot, adstageData);
|
|
@@ -2265,6 +2531,32 @@ class AdsModule {
|
|
|
2265
2531
|
this.renderFallback(slot);
|
|
2266
2532
|
}
|
|
2267
2533
|
}
|
|
2534
|
+
/**
|
|
2535
|
+
* ๋ฐฐ๋ ๊ด๊ณ ๋ฅผ ์ํ ์ปจํ
์ด๋ ์ต์ ํ
|
|
2536
|
+
*/
|
|
2537
|
+
async optimizeContainerForBannerAds(slot, advertisements) {
|
|
2538
|
+
try {
|
|
2539
|
+
const container = document.getElementById(slot.containerId);
|
|
2540
|
+
const adElement = document.getElementById(slot.id);
|
|
2541
|
+
if (!container || !adElement)
|
|
2542
|
+
return;
|
|
2543
|
+
// ํ์ฌ ์ปจํ
์ด๋ ๋๋น ํ์ธ
|
|
2544
|
+
const containerWidth = container.getBoundingClientRect().width || 300;
|
|
2545
|
+
// ์ต์ ํฌ๊ธฐ ๊ณ์ฐ
|
|
2546
|
+
const optimalSize = await this.calculateOptimalContainerSize(advertisements, containerWidth, slot.adType);
|
|
2547
|
+
// ์ปจํ
์ด๋ ํฌ๊ธฐ ๋์ ์กฐ์
|
|
2548
|
+
adElement.style.height = optimalSize.height;
|
|
2549
|
+
// ์ฌ๋กฏ ์ ๋ณด ์
๋ฐ์ดํธ
|
|
2550
|
+
slot.optimizedHeight = optimalSize.height;
|
|
2551
|
+
slot.aspectRatio = optimalSize.aspectRatio;
|
|
2552
|
+
if (this._config?.debug) {
|
|
2553
|
+
console.log(`๐ง Container optimized for ${advertisements.length} banner ads: ${optimalSize.height}`);
|
|
2554
|
+
}
|
|
2555
|
+
}
|
|
2556
|
+
catch (error) {
|
|
2557
|
+
console.warn('Container optimization failed, using default size:', error);
|
|
2558
|
+
}
|
|
2559
|
+
}
|
|
2268
2560
|
/**
|
|
2269
2561
|
* ๊ธฐ๋ณธ viewability ์ถ์ ์์
|
|
2270
2562
|
*/
|
|
@@ -2487,23 +2779,25 @@ class AdsModule {
|
|
|
2487
2779
|
}
|
|
2488
2780
|
};
|
|
2489
2781
|
let sliderElement;
|
|
2782
|
+
// ์ต์ ํ๋ ์ฌ๋ผ์ด๋ ์ต์
์ค๋น
|
|
2783
|
+
const optimizedSliderOptions = {
|
|
2784
|
+
autoSlideInterval: (slot.config?.slideInterval || 5000) / 1000,
|
|
2785
|
+
...slot.config,
|
|
2786
|
+
// ๐ ๋์ ํฌ๊ธฐ ์ ๋ณด ์ ๋ฌ
|
|
2787
|
+
optimizedHeight: slot.optimizedHeight,
|
|
2788
|
+
aspectRatio: slot.aspectRatio
|
|
2789
|
+
};
|
|
2490
2790
|
// ํ
์คํธ ๊ด๊ณ ๋ TextTransitionManager ์ฌ์ฉ, ๊ทธ ์ธ๋ CarouselSliderManager ์ฌ์ฉ
|
|
2491
2791
|
if (slot.adType === AdType.TEXT) {
|
|
2492
|
-
sliderElement = TextTransitionManager.createTextTransitionContainer(slot, advertisements,
|
|
2493
|
-
autoSlideInterval: (slot.config?.slideInterval || 5000) / 1000,
|
|
2494
|
-
...slot.config
|
|
2495
|
-
}, trackEventCallback);
|
|
2792
|
+
sliderElement = TextTransitionManager.createTextTransitionContainer(slot, advertisements, optimizedSliderOptions, trackEventCallback);
|
|
2496
2793
|
if (this._config?.debug) {
|
|
2497
2794
|
console.log(`โจ Text transition created for TEXT slot: ${slot.id} with ${advertisements.length} ads`);
|
|
2498
2795
|
}
|
|
2499
2796
|
}
|
|
2500
2797
|
else {
|
|
2501
|
-
sliderElement = CarouselSliderManager.createSliderContainer(slot, advertisements,
|
|
2502
|
-
autoSlideInterval: (slot.config?.slideInterval || 5000) / 1000,
|
|
2503
|
-
...slot.config
|
|
2504
|
-
}, trackEventCallback);
|
|
2798
|
+
sliderElement = CarouselSliderManager.createSliderContainer(slot, advertisements, optimizedSliderOptions, trackEventCallback);
|
|
2505
2799
|
if (this._config?.debug) {
|
|
2506
|
-
console.log(`๐ Carousel slider created for ${slot.adType} slot: ${slot.id} with ${advertisements.length} ads`);
|
|
2800
|
+
console.log(`๐ Carousel slider created for ${slot.adType} slot: ${slot.id} with ${advertisements.length} ads (optimized: ${slot.optimizedHeight || 'default'})`);
|
|
2507
2801
|
}
|
|
2508
2802
|
}
|
|
2509
2803
|
// ๊ธฐ์กด ๋ด์ฉ ์ ๊ฑฐํ๊ณ ์ฌ๋ผ์ด๋ ์ถ๊ฐ
|
|
@@ -2530,19 +2824,23 @@ class AdsModule {
|
|
|
2530
2824
|
// ๊ธฐ๋ณธ HTML ๊ตฌ์กฐ ์์ฑ
|
|
2531
2825
|
const adElement = document.createElement('div');
|
|
2532
2826
|
adElement.className = 'adstage-ad';
|
|
2533
|
-
|
|
2534
|
-
|
|
2827
|
+
// ์ค๋งํธํ ํฌ๊ธฐ ์ค์ - ์ต์ ํ๋ ํฌ๊ธฐ๊ฐ ์์ผ๋ฉด ์ฌ์ฉ
|
|
2828
|
+
const optimizedHeight = slot.optimizedHeight;
|
|
2829
|
+
const containerElement = container.parentElement || container;
|
|
2830
|
+
if (optimizedHeight) {
|
|
2831
|
+
adElement.style.width = '100%';
|
|
2832
|
+
adElement.style.height = optimizedHeight;
|
|
2833
|
+
}
|
|
2834
|
+
else {
|
|
2835
|
+
const { width, height } = this.calculateAdSize(containerElement, slot.adType, slot.config || {});
|
|
2836
|
+
adElement.style.width = width;
|
|
2837
|
+
adElement.style.height = height;
|
|
2838
|
+
}
|
|
2535
2839
|
// ๊ด๊ณ ํ์
๋ณ ๋ ๋๋ง
|
|
2536
2840
|
switch (slot.adType) {
|
|
2537
2841
|
case AdType.BANNER:
|
|
2538
2842
|
if (ad.imageUrl) {
|
|
2539
|
-
|
|
2540
|
-
img.src = ad.imageUrl;
|
|
2541
|
-
img.alt = ad.title;
|
|
2542
|
-
img.style.width = '100%';
|
|
2543
|
-
img.style.height = '100%';
|
|
2544
|
-
img.style.objectFit = 'cover';
|
|
2545
|
-
adElement.appendChild(img);
|
|
2843
|
+
await this.renderOptimizedBannerImage(adElement, ad, slot);
|
|
2546
2844
|
}
|
|
2547
2845
|
break;
|
|
2548
2846
|
case AdType.TEXT:
|
|
@@ -2577,6 +2875,50 @@ class AdsModule {
|
|
|
2577
2875
|
container.innerHTML = '';
|
|
2578
2876
|
container.appendChild(adElement);
|
|
2579
2877
|
}
|
|
2878
|
+
/**
|
|
2879
|
+
* ์ต์ ํ๋ ๋ฐฐ๋ ์ด๋ฏธ์ง ๋ ๋๋ง
|
|
2880
|
+
*/
|
|
2881
|
+
async renderOptimizedBannerImage(adElement, ad, slot) {
|
|
2882
|
+
try {
|
|
2883
|
+
// ์ด๋ฏธ์ง ํฌ๊ธฐ ์ ๋ณด ๋ก๋
|
|
2884
|
+
const imageDimensions = await this.loadImageDimensions(ad.imageUrl);
|
|
2885
|
+
const imageAspectRatio = imageDimensions.width / imageDimensions.height;
|
|
2886
|
+
// ์ปจํ
์ด๋ ๋น์จ ๊ณ์ฐ
|
|
2887
|
+
const containerAspectRatio = slot.aspectRatio || 16 / 9;
|
|
2888
|
+
// ์ด๋ฏธ์ง ์์ ์์ฑ
|
|
2889
|
+
const img = document.createElement('img');
|
|
2890
|
+
img.src = ad.imageUrl;
|
|
2891
|
+
img.alt = ad.title;
|
|
2892
|
+
img.style.width = '100%';
|
|
2893
|
+
img.style.height = '100%';
|
|
2894
|
+
// ๐จ ์ต์ ํ๋ ์คํ์ผ ์ ์ฉ
|
|
2895
|
+
this.applyOptimizedImageStyle(img, imageAspectRatio, containerAspectRatio);
|
|
2896
|
+
// ์ด๋ฏธ์ง ๋ก๋ ์๋ฃ ์ฒ๋ฆฌ
|
|
2897
|
+
img.onload = () => {
|
|
2898
|
+
if (this._config?.debug) {
|
|
2899
|
+
console.log(`๐ผ๏ธ Optimized banner image loaded: ${imageDimensions.width}x${imageDimensions.height} (ratio: ${imageAspectRatio.toFixed(2)})`);
|
|
2900
|
+
}
|
|
2901
|
+
};
|
|
2902
|
+
// ์๋ฌ ์ฒ๋ฆฌ
|
|
2903
|
+
img.onerror = () => {
|
|
2904
|
+
console.warn(`Failed to load banner image: ${ad.imageUrl}`);
|
|
2905
|
+
// ํด๋ฐฑ ํ
์คํธ ํ์
|
|
2906
|
+
adElement.innerHTML = `<div style="display: flex; align-items: center; justify-content: center; background: #f0f0f0; color: #666;">${ad.title}</div>`;
|
|
2907
|
+
};
|
|
2908
|
+
adElement.appendChild(img);
|
|
2909
|
+
}
|
|
2910
|
+
catch (error) {
|
|
2911
|
+
console.warn('Failed to optimize banner image, using fallback:', error);
|
|
2912
|
+
// ๊ธฐ๋ณธ ์ด๋ฏธ์ง ๋ ๋๋ง (ํด๋ฐฑ)
|
|
2913
|
+
const img = document.createElement('img');
|
|
2914
|
+
img.src = ad.imageUrl;
|
|
2915
|
+
img.alt = ad.title;
|
|
2916
|
+
img.style.width = '100%';
|
|
2917
|
+
img.style.height = '100%';
|
|
2918
|
+
img.style.objectFit = 'cover';
|
|
2919
|
+
adElement.appendChild(img);
|
|
2920
|
+
}
|
|
2921
|
+
}
|
|
2580
2922
|
/**
|
|
2581
2923
|
* ๊ด๊ณ ์ฌ๋กฏ ์๋ก๊ณ ์นจ
|
|
2582
2924
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adstage/web-sdk",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.4",
|
|
4
4
|
"description": "AdStage Web SDK - Production-ready marketing platform SDK with namespace architecture for ads, events, and config management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs.js",
|