add
@@ -1,3 +0,0 @@
|
|||||||
<?php if (!defined('_GNUBOARD_')) exit; ?>
|
|
||||||
|
|
||||||
YTozOntzOjQ6InRpbWUiO2k6MTc3MzE5NDI1ODtzOjM6InR0bCI7aToxMDgwMDtzOjQ6ImRhdGEiO047fQ==
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<?php if (!defined('_GNUBOARD_')) exit; ?>
|
|
||||||
|
|
||||||
YTozOntzOjQ6InRpbWUiO2k6MTc4MDMyODU3NTtzOjM6InR0bCI7aToxMDgwMDtzOjQ6ImRhdGEiO047fQ==
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<?php if (!defined('_GNUBOARD_')) exit; ?>
|
|
||||||
|
|
||||||
YTozOntzOjQ6InRpbWUiO2k6MTc3MzEyNDIzODtzOjM6InR0bCI7aToxMDgwMDtzOjQ6ImRhdGEiO2E6MTQ6e3M6NToiY29faWQiO3M6NzoiY29tcGFueSI7czo3OiJjb19odG1sIjtzOjE6IjEiO3M6MTA6ImNvX3N1YmplY3QiO3M6MTI6Iu2ajOyCrOyGjOqwnCI7czoxMDoiY29fY29udGVudCI7czo3OToiPHAgYWxpZ249Y2VudGVyPjxiPu2ajOyCrOyGjOqwnOyXkCDrjIDtlZwg64K07Jqp7J2EIOyeheugpe2VmOyLreyLnOyYpC48L2I+PC9wPiI7czoxMjoiY29fc2VvX3RpdGxlIjtzOjA6IiI7czoxNzoiY29fbW9iaWxlX2NvbnRlbnQiO3M6MDoiIjtzOjc6ImNvX3NraW4iO3M6NToiYmFzaWMiO3M6MTQ6ImNvX21vYmlsZV9za2luIjtzOjU6ImJhc2ljIjtzOjE3OiJjb190YWdfZmlsdGVyX3VzZSI7czoxOiIwIjtzOjY6ImNvX2hpdCI7czoxOiIwIjtzOjE1OiJjb19pbmNsdWRlX2hlYWQiO3M6MDoiIjtzOjE1OiJjb19pbmNsdWRlX3RhaWwiO3M6MDoiIjtzOjg6ImNvX2xldmVsIjtzOjE6IjEiO3M6MTI6ImNvX2xldmVsX29wdCI7czoxOiIxIjt9fQ==
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<?php if (!defined('_GNUBOARD_')) exit; ?>
|
|
||||||
|
|
||||||
YTozOntzOjQ6InRpbWUiO2k6MTc4MDMyODU3NTtzOjM6InR0bCI7aToxMDgwMDtzOjQ6ImRhdGEiO2E6MTQ6e3M6NToiY29faWQiO3M6NzoiY29tcGFueSI7czo3OiJjb19odG1sIjtzOjE6IjEiO3M6MTA6ImNvX3N1YmplY3QiO3M6MTI6Iu2ajOyCrOyGjOqwnCI7czoxMDoiY29fY29udGVudCI7czo3OToiPHAgYWxpZ249Y2VudGVyPjxiPu2ajOyCrOyGjOqwnOyXkCDrjIDtlZwg64K07Jqp7J2EIOyeheugpe2VmOyLreyLnOyYpC48L2I+PC9wPiI7czoxMjoiY29fc2VvX3RpdGxlIjtzOjA6IiI7czoxNzoiY29fbW9iaWxlX2NvbnRlbnQiO3M6MDoiIjtzOjc6ImNvX3NraW4iO3M6NToiYmFzaWMiO3M6MTQ6ImNvX21vYmlsZV9za2luIjtzOjU6ImJhc2ljIjtzOjE3OiJjb190YWdfZmlsdGVyX3VzZSI7czoxOiIwIjtzOjY6ImNvX2hpdCI7czoxOiIwIjtzOjE1OiJjb19pbmNsdWRlX2hlYWQiO3M6MDoiIjtzOjE1OiJjb19pbmNsdWRlX3RhaWwiO3M6MDoiIjtzOjg6ImNvX2xldmVsIjtzOjE6IjEiO3M6MTI6ImNvX2xldmVsX29wdCI7czoxOiIxIjt9fQ==
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<?php if (!defined('_GNUBOARD_')) exit; ?>
|
|
||||||
|
|
||||||
YTozOntzOjQ6InRpbWUiO2k6MTc3MzE5NDI1ODtzOjM6InR0bCI7aToxMDgwMDtzOjQ6ImRhdGEiO2E6MTQ6e3M6NToiY29faWQiO3M6OToicHJvdmlzaW9uIjtzOjc6ImNvX2h0bWwiO3M6MToiMSI7czoxMDoiY29fc3ViamVjdCI7czoyMjoi7ISc67mE7IqkIOydtOyaqeyVveq0gCI7czoxMDoiY29fY29udGVudCI7czo4OToiPHAgYWxpZ249Y2VudGVyPjxiPuyEnOu5hOyKpCDsnbTsmqnslb3qtIDsl5Ag64yA7ZWcIOuCtOyaqeydhCDsnoXroKXtlZjsi63si5zsmKQuPC9iPjwvcD4iO3M6MTI6ImNvX3Nlb190aXRsZSI7czowOiIiO3M6MTc6ImNvX21vYmlsZV9jb250ZW50IjtzOjA6IiI7czo3OiJjb19za2luIjtzOjU6ImJhc2ljIjtzOjE0OiJjb19tb2JpbGVfc2tpbiI7czo1OiJiYXNpYyI7czoxNzoiY29fdGFnX2ZpbHRlcl91c2UiO3M6MToiMCI7czo2OiJjb19oaXQiO3M6MToiMCI7czoxNToiY29faW5jbHVkZV9oZWFkIjtzOjA6IiI7czoxNToiY29faW5jbHVkZV90YWlsIjtzOjA6IiI7czo4OiJjb19sZXZlbCI7czoxOiIxIjtzOjEyOiJjb19sZXZlbF9vcHQiO3M6MToiMSI7fX0=
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<?php if (!defined('_GNUBOARD_')) exit; ?>
|
|
||||||
|
|
||||||
YTozOntzOjQ6InRpbWUiO2k6MTc4MDMyODU5MTtzOjM6InR0bCI7aToxMDgwMDtzOjQ6ImRhdGEiO2E6MTQ6e3M6NToiY29faWQiO3M6OToicHJvdmlzaW9uIjtzOjc6ImNvX2h0bWwiO3M6MToiMSI7czoxMDoiY29fc3ViamVjdCI7czoyMjoi7ISc67mE7IqkIOydtOyaqeyVveq0gCI7czoxMDoiY29fY29udGVudCI7czo4OToiPHAgYWxpZ249Y2VudGVyPjxiPuyEnOu5hOyKpCDsnbTsmqnslb3qtIDsl5Ag64yA7ZWcIOuCtOyaqeydhCDsnoXroKXtlZjsi63si5zsmKQuPC9iPjwvcD4iO3M6MTI6ImNvX3Nlb190aXRsZSI7czowOiIiO3M6MTc6ImNvX21vYmlsZV9jb250ZW50IjtzOjA6IiI7czo3OiJjb19za2luIjtzOjU6ImJhc2ljIjtzOjE0OiJjb19tb2JpbGVfc2tpbiI7czo1OiJiYXNpYyI7czoxNzoiY29fdGFnX2ZpbHRlcl91c2UiO3M6MToiMCI7czo2OiJjb19oaXQiO3M6MToiMCI7czoxNToiY29faW5jbHVkZV9oZWFkIjtzOjA6IiI7czoxNToiY29faW5jbHVkZV90YWlsIjtzOjA6IiI7czo4OiJjb19sZXZlbCI7czoxOiIxIjtzOjEyOiJjb19sZXZlbF9vcHQiO3M6MToiMSI7fX0=
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<?php if (!defined('_GNUBOARD_')) exit; ?>
|
|
||||||
|
|
||||||
YTozOntzOjQ6InRpbWUiO2k6MTc4MDcyMTM5NTtzOjM6InR0bCI7aTozNjAwO3M6NDoiZGF0YSI7YToyOntzOjQ6Imxpc3QiO2E6MTp7aTowO2E6NjY6e3M6NToid3JfaWQiO3M6MToiMSI7czo2OiJ3cl9udW0iO3M6MjoiLTEiO3M6ODoid3JfcmVwbHkiO3M6MDoiIjtzOjk6IndyX3BhcmVudCI7czoxOiIxIjtzOjEzOiJ3cl9pc19jb21tZW50IjtzOjE6IjAiO3M6MTA6IndyX2NvbW1lbnQiO3M6MToiMCI7czoxNjoid3JfY29tbWVudF9yZXBseSI7czowOiIiO3M6NzoiY2FfbmFtZSI7czowOiIiO3M6OToid3Jfb3B0aW9uIjtzOjU6Imh0bWwyIjtzOjEwOiJ3cl9zdWJqZWN0IjtzOjM4OiLsoJztkogg7ISk7LmYIOq0gOugqCDrrLjsnZgg7J6F64uI64ukLiI7czoxMDoid3JfY29udGVudCI7czoyNDc6IjxwPuqyrOyggSDrrLjsnZgg65Oc66a964uI64ukLjwvcD4NCjxwPjxpbWcgc3JjPSJodHRwOi8vbG9jYWxob3N0L2RhdGEvZWRpdG9yLzI2MDYvMjAyNjA2MDYxMzQ5NDFfNzVjYTQ0NmQyOTU0ODNmM2Q1MjE0OGU3OTZiNmQ0Y2ZfOGx0ei5qcGciIGFsdD0iMjAyNjA2MDIyMDIyMTFfODE2NjFjNzJiMTgyYzRkZTIwNjNjNzM5NDRjYjhjNzVfbXlzbC5qcGciIHN0eWxlPSJ3aWR0aDogODAwcHg7IGhlaWdodDogMzUzcHg7IiAvPjwvcD4iO3M6MTI6IndyX3Nlb190aXRsZSI7czozNzoi7KCc7ZKILeyEpOy5mC3qtIDroKgt66y47J2YLeyeheuLiOuLpCI7czo4OiJ3cl9saW5rMSI7czowOiIiO3M6ODoid3JfbGluazIiO3M6MDoiIjtzOjEyOiJ3cl9saW5rMV9oaXQiO3M6MToiMCI7czoxMjoid3JfbGluazJfaGl0IjtzOjE6IjAiO3M6Njoid3JfaGl0IjtzOjE6IjciO3M6Nzoid3JfZ29vZCI7czoxOiIwIjtzOjk6IndyX25vZ29vZCI7czoxOiIwIjtzOjU6Im1iX2lkIjtzOjU6ImFkbWluIjtzOjc6IndyX25hbWUiO3M6MTU6Iuy1nOqzoOq0gOumrOyekCI7czo4OiJ3cl9lbWFpbCI7czowOiIiO3M6MTE6IndyX2hvbWVwYWdlIjtzOjA6IiI7czoxMToid3JfZGF0ZXRpbWUiO3M6MTk6IjIwMjYtMDUtMjUgMTA6MTg6MzQiO3M6Nzoid3JfZmlsZSI7czoxOiIxIjtzOjc6IndyX2xhc3QiO3M6MTk6IjIwMjYtMDUtMjUgMTA6MTg6MzQiO3M6NToid3JfaXAiO3M6MzoiOjoxIjtzOjE2OiJ3cl9mYWNlYm9va191c2VyIjtzOjA6IiI7czoxNToid3JfdHdpdHRlcl91c2VyIjtzOjA6IiI7czo0OiJ3cl8xIjtzOjk6IuyVhO2MjO2KuCI7czo0OiJ3cl8yIjtzOjA6IiI7czo0OiJ3cl8zIjtzOjA6IiI7czo0OiJ3cl80IjtzOjA6IiI7czo0OiJ3cl81IjtzOjA6IiI7czo0OiJ3cl82IjtzOjA6IiI7czo0OiJ3cl83IjtzOjA6IiI7czo0OiJ3cl84IjtzOjA6IiI7czo0OiJ3cl85IjtzOjA6IiI7czo1OiJ3cl8xMCI7czowOiIiO3M6MTQ6IndyX2lzX3Jlc2VydmVkIjtzOjE6IjAiO3M6MTc6IndyX3Jlc2VydmVkX3N0YXJ0IjtzOjE5OiIyMDI2LTA1LTI1IDAxOjE4OjM0IjtzOjE1OiJ3cl9yZXNlcnZlZF9lbmQiO3M6MTk6IjIwMjYtMDUtMjUgMDE6MTg6MzQiO3M6OToiaXNfbm90aWNlIjtiOjA7czo3OiJzdWJqZWN0IjtzOjM4OiLsoJztkogg7ISk7LmYIOq0gOugqCDrrLjsnZgg7J6F64uI64ukLiI7czoxMToiY29tbWVudF9jbnQiO3M6MDoiIjtzOjg6ImRhdGV0aW1lIjtzOjEwOiIyMDI2LTA1LTI1IjtzOjk6ImRhdGV0aW1lMiI7czo1OiIwNS0yNSI7czo0OiJsYXN0IjtzOjEwOiIyMDI2LTA1LTI1IjtzOjU6Imxhc3QyIjtzOjU6IjA1LTI1IjtzOjQ6Im5hbWUiO3M6NDY6IjxzcGFuIGNsYXNzPSJzdl9tZW1iZXIiPuy1nOqzoOq0gOumrOyekDwvc3Bhbj4iO3M6NToicmVwbHkiO2k6MDtzOjEwOiJpY29uX3JlcGx5IjtzOjA6IiI7czo5OiJpY29uX2xpbmsiO3M6MDoiIjtzOjEyOiJjYV9uYW1lX2hyZWYiO3M6NTM6Imh0dHA6Ly9sb2NhbGhvc3QvYmJzL2JvYXJkLnBocD9ib190YWJsZT1hYWFhJmFtcDtzY2E9IjtzOjQ6ImhyZWYiO3M6NTY6Imh0dHA6Ly9sb2NhbGhvc3QvYmJzL2JvYXJkLnBocD9ib190YWJsZT1hYWFhJmFtcDt3cl9pZD0xIjtzOjEyOiJjb21tZW50X2hyZWYiO3M6NTY6Imh0dHA6Ly9sb2NhbGhvc3QvYmJzL2JvYXJkLnBocD9ib190YWJsZT1hYWFhJmFtcDt3cl9pZD0xIjtzOjg6Imljb25fbmV3IjtzOjA6IiI7czo4OiJpY29uX2hvdCI7czowOiIiO3M6MTE6Imljb25fc2VjcmV0IjtzOjA6IiI7czo0OiJsaW5rIjthOjI6e2k6MTtOO2k6MjtOO31zOjk6ImxpbmtfaHJlZiI7YToyOntpOjE7czo2NDoiaHR0cDovL2xvY2FsaG9zdC9iYnMvbGluay5waHA/Ym9fdGFibGU9YWFhYSZhbXA7d3JfaWQ9MSZhbXA7bm89MSI7aToyO3M6NjQ6Imh0dHA6Ly9sb2NhbGhvc3QvYmJzL2xpbmsucGhwP2JvX3RhYmxlPWFhYWEmYW1wO3dyX2lkPTEmYW1wO25vPTIiO31zOjg6ImxpbmtfaGl0IjthOjI6e2k6MTtpOjA7aToyO2k6MDt9czo0OiJmaWxlIjthOjE6e3M6NToiY291bnQiO3M6MToiMSI7fXM6OToiaWNvbl9maWxlIjtzOjUwOiI8aSBjbGFzcz0iZmEgZmEtZG93bmxvYWQiIGFyaWEtaGlkZGVuPSJ0cnVlIj48L2k+ICI7czoxNjoiZmlyc3RfZmlsZV90aHVtYiI7YToyOntzOjc6ImJmX2ZpbGUiO3M6ODY6ImJlNDBjZDBjZDAxMjA5YjRhMjE0MjNmODVmZTI0NjExX1FPN2N2dEdTX2JmYmI1OTM0MjQxNzY0ZDQ2ZjE2ZjhjMGE2M2VlYWU5ZWFhMTY1ZDIuanBnIjtzOjEwOiJiZl9jb250ZW50IjtzOjA6IiI7fXM6ODoiYm9fdGFibGUiO3M6NDoiYWFhYSI7fX1zOjEwOiJib19zdWJqZWN0IjtzOjk6IuydtOuBjOumvCI7fX0=
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<?php if (!defined('_GNUBOARD_')) exit; ?>
|
|
||||||
|
|
||||||
YTozOntzOjQ6InRpbWUiO2k6MTc3MzEwMTI1NjtzOjM6InR0bCI7aTozNjAwO3M6NDoiZGF0YSI7YToyOntzOjQ6Imxpc3QiO2E6MDp7fXM6MTA6ImJvX3N1YmplY3QiO3M6OToi6rCk65+s66asIjt9fQ==
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<?php if (!defined('_GNUBOARD_')) exit; ?>
|
|
||||||
|
|
||||||
YTozOntzOjQ6InRpbWUiO2k6MTc3NDkxNzI0NDtzOjM6InR0bCI7aTozNjAwO3M6NDoiZGF0YSI7YToyOntpOjA7YToxOTp7czo1OiJtZV9pZCI7czoyOiIxNSI7czoxMjoibWVfcGFyZW50X2lkIjtzOjE6IjAiO3M6ODoibWVfZGVwdGgiO3M6MToiMSI7czo3OiJtZV9jb2RlIjtzOjA6IiI7czo3OiJtZV9uYW1lIjtzOjEyOiLqsqzsoIHrrLjsnZgiO3M6NzoibWVfbGluayI7czo2MDoiaHR0cHM6Ly9kbnNzYXNoLmRza2ltLmtvem93LmNvbS9iYnMvYm9hcmQucGhwP2JvX3RhYmxlPW9yZGVyIjtzOjk6Im1lX3RhcmdldCI7czo0OiJzZWxmIjtzOjg6Im1lX29yZGVyIjtzOjE6IjAiO3M6NjoibWVfdXNlIjtzOjE6IjEiO3M6MTM6Im1lX21vYmlsZV91c2UiO3M6MToiMSI7czo4OiJtZV9sZXZlbCI7czoxOiIxIjtzOjEyOiJtZV9sZXZlbF9vcHQiO3M6MToiMSI7czoxMzoibWVfY3JlYXRlZF9ieSI7czo1OiJhZG1pbiI7czoxMzoibWVfdXBkYXRlZF9ieSI7czo1OiJhZG1pbiI7czoxMzoibWVfY3JlYXRlZF9hdCI7czoxOToiMjAyNi0wMS0yOSAxMzo1MzoyMCI7czoxMzoibWVfdXBkYXRlZF9hdCI7czoxOToiMjAyNi0wMy0xMyAxMDoxMToyNCI7czoxMzoibWVfZGVsZXRlZF9hdCI7TjtzOjExOiJvcmlfbWVfbGluayI7czo0NToiaHR0cDovL2xvY2FsaG9zdC9iYnMvYm9hcmQucGhwP2JvX3RhYmxlPW9yZGVyIjtzOjM6InN1YiI7YTowOnt9fWk6MTthOjE5OntzOjU6Im1lX2lkIjtzOjI6IjE5IjtzOjEyOiJtZV9wYXJlbnRfaWQiO3M6MToiMCI7czo4OiJtZV9kZXB0aCI7czoxOiIxIjtzOjc6Im1lX2NvZGUiO3M6MDoiIjtzOjc6Im1lX25hbWUiO3M6MTI6IuygnO2SiOyGjOqwnCI7czo3OiJtZV9saW5rIjtzOjYyOiJodHRwczovL2Ruc3Nhc2guZHNraW0ua296b3cuY29tL2Jicy9ib2FyZC5waHA/Ym9fdGFibGU9cHJvZHVjdCI7czo5OiJtZV90YXJnZXQiO3M6NDoic2VsZiI7czo4OiJtZV9vcmRlciI7czoxOiIxIjtzOjY6Im1lX3VzZSI7czoxOiIxIjtzOjEzOiJtZV9tb2JpbGVfdXNlIjtzOjE6IjEiO3M6ODoibWVfbGV2ZWwiO3M6MToiMSI7czoxMjoibWVfbGV2ZWxfb3B0IjtzOjE6IjEiO3M6MTM6Im1lX2NyZWF0ZWRfYnkiO3M6NToiYWRtaW4iO3M6MTM6Im1lX3VwZGF0ZWRfYnkiO3M6NToiYWRtaW4iO3M6MTM6Im1lX2NyZWF0ZWRfYXQiO3M6MTk6IjIwMjYtMDEtMjkgMTY6NDI6NTQiO3M6MTM6Im1lX3VwZGF0ZWRfYXQiO3M6MTk6IjIwMjYtMDMtMTMgMTA6Mzk6MTYiO3M6MTM6Im1lX2RlbGV0ZWRfYXQiO047czoxMToib3JpX21lX2xpbmsiO3M6NDc6Imh0dHA6Ly9sb2NhbGhvc3QvYmJzL2JvYXJkLnBocD9ib190YWJsZT1wcm9kdWN0IjtzOjM6InN1YiI7YTowOnt9fX19
|
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
.product-section .product-item { display: flex; align-items: center; gap: 20px; margin-bottom: 40px; position: relative; z-index: 10; }
|
.product-section .product-item { display: flex; align-items: center; gap: 20px; margin-bottom: 40px; position: relative; z-index: 10; }
|
||||||
|
|
||||||
/* 2. 제품 이미지 기본 스타일 (200x200) */
|
/* 2. 제품 이미지 기본 스타일 (200x200) */
|
||||||
.product-img { width: 200px; height: 200px; overflow: visible; position: relative; }
|
.product-img { width: 100px; height: 100px; overflow: visible; position: relative; }
|
||||||
.product-img img { width: 100%; height: 100%; object-fit: cover; border-radius: 12px; transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1); box-shadow: 0 4px 15px rgba(0,0,0,0.3); }
|
.product-img img { width: 100%; height: 100%; object-fit: cover; border-radius: 12px; transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1); box-shadow: 0 4px 15px rgba(0,0,0,0.3); }
|
||||||
|
|
||||||
/* 💡 [모드 1] 메인 영역 내부 중앙 팝업 */
|
/* 💡 [모드 1] 메인 영역 내부 중앙 팝업 */
|
||||||
|
|||||||
@@ -1,326 +0,0 @@
|
|||||||
/* ============================================================
|
|
||||||
[최종 통합본] 메인 맵 전용 스타일 - 화살표 및 방향 보정 포함
|
|
||||||
============================================================ */
|
|
||||||
|
|
||||||
/* 1. 기본 레이아웃 */
|
|
||||||
.product-section {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: 40px;
|
|
||||||
padding: 40px 20px;
|
|
||||||
position: relative !important;
|
|
||||||
}
|
|
||||||
.product-section .product-side { display: flex; flex-direction: column; }
|
|
||||||
.product-section .product-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 20px;
|
|
||||||
margin-bottom: 40px;
|
|
||||||
position: relative;
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 2. 제품 이미지 기본 스타일 */
|
|
||||||
.product-img { width: 200px; height: 200px; overflow: visible; position: relative; }
|
|
||||||
.product-img img {
|
|
||||||
width: 100%; height: 100%; object-fit: cover; border-radius: 12px;
|
|
||||||
transition: all 0.4s ease; box-shadow: 0 4px 15px rgba(0,0,0,0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 💡 [모드 1] 메인 영역 내부 중앙 팝업 */
|
|
||||||
#active-popup-img {
|
|
||||||
position: absolute !important;
|
|
||||||
top: 50% !important; left: 50% !important;
|
|
||||||
transform: translate(-50%, -50%) scale(0.1) !important;
|
|
||||||
width: calc(100% - 40px) !important;
|
|
||||||
height: calc(100% - 40px) !important;
|
|
||||||
max-width: 1560px;
|
|
||||||
z-index: 9999 !important;
|
|
||||||
box-shadow: 0 40px 100px rgba(0,0,0,0.8);
|
|
||||||
border: 3px solid rgba(255,255,255,0.5);
|
|
||||||
object-fit: contain !important;
|
|
||||||
opacity: 0;
|
|
||||||
transition: transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.3s ease;
|
|
||||||
pointer-events: none !important;
|
|
||||||
}
|
|
||||||
#active-popup-img.active { transform: translate(-50%, -50%) scale(1) !important; opacity: 1; }
|
|
||||||
|
|
||||||
/* 💡 점선 연결선 설정 (After: 선, Before: 화살표) */
|
|
||||||
.show-connector::after {
|
|
||||||
content: ''; position: absolute; top: 50%;
|
|
||||||
border-top: 3px dashed #ffd200; z-index: 500; pointer-events: none;
|
|
||||||
width: 0 !important;
|
|
||||||
transform: rotate(var(--line-angle, 0deg)) !important;
|
|
||||||
transition: width 0.5s ease;
|
|
||||||
display: block !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 💡 [추가] 점선 끝 화살표 머리 */
|
|
||||||
.show-connector::before {
|
|
||||||
content: ''; position: absolute; top: 50%;
|
|
||||||
width: 0; height: 0;
|
|
||||||
border-left: 12px solid #ffd200; /* 화살표 색상 */
|
|
||||||
border-top: 7px solid transparent;
|
|
||||||
border-bottom: 7px solid transparent;
|
|
||||||
z-index: 501; pointer-events: none;
|
|
||||||
opacity: 0;
|
|
||||||
/* 선의 끝 지점으로 화살표 이동 */
|
|
||||||
transform: rotate(var(--line-angle, 0deg)) translateX(var(--line-width, 0px)) translateY(-50%);
|
|
||||||
transition: opacity 0.3s ease 0.4s;
|
|
||||||
display: block !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.show-connector.active::after { width: var(--line-width, 0px) !important; animation: dash-move 1.5s linear infinite; }
|
|
||||||
.show-connector.active::before { opacity: 1; }
|
|
||||||
|
|
||||||
/* 💡 방향별 회전축 보정 */
|
|
||||||
/* 왼쪽 메뉴 -> 메인으로 (오른쪽 방향) */
|
|
||||||
.product-side.left .show-connector::after,
|
|
||||||
.product-side.left .show-connector::before {
|
|
||||||
left: 100% !important;
|
|
||||||
margin-left: 10px;
|
|
||||||
transform-origin: left center !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 오른쪽 메뉴 -> 메인으로 (왼쪽 방향) */
|
|
||||||
.product-side.right .show-connector::after,
|
|
||||||
.product-side.right .show-connector::before {
|
|
||||||
right: 100% !important; /* 👈 오른쪽 끝 기준 왼쪽으로 뻗음 */
|
|
||||||
left: auto !important;
|
|
||||||
margin-right: 10px;
|
|
||||||
transform-origin: right center !important; /* 👈 회전축을 우측 끝으로 고정 */
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes dash-move { to { stroke-dashoffset: -20; } }
|
|
||||||
|
|
||||||
/* 3. 메인 이미지 및 블루 스폿 설정 */
|
|
||||||
.product-main { position: relative; width: 1600px; height: 1200px; flex-shrink: 0; overflow: hidden; }
|
|
||||||
.product-main img { width: 100%; height: 100%; object-fit: cover; }
|
|
||||||
|
|
||||||
.product-hotspot {
|
|
||||||
position: absolute !important; width: 45px !important; height: 45px !important;
|
|
||||||
background: rgba(0, 123, 255, 0.8) !important; border: 3px solid #fff !important;
|
|
||||||
border-radius: 50% !important; transform: translate(-50%, -50%) !important;
|
|
||||||
z-index: 500; display: none; animation: hotspot-pulse-blue 1.5s infinite;
|
|
||||||
}
|
|
||||||
@keyframes hotspot-pulse-blue {
|
|
||||||
0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.8; }
|
|
||||||
50% { transform: translate(-50%, -50%) scale(1.4); opacity: 1; }
|
|
||||||
}
|
|
||||||
/*잘되은거 아래*/
|
|
||||||
/*!* ============================================================
|
|
||||||
[최종 통합본] 메인 맵 전용 스타일 (products2.css)
|
|
||||||
============================================================ *!
|
|
||||||
|
|
||||||
!* 1. 기본 레이아웃 *!
|
|
||||||
.product-section {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: 40px;
|
|
||||||
padding: 40px 20px;
|
|
||||||
position: relative !important;
|
|
||||||
}
|
|
||||||
.product-section .product-side { display: flex; flex-direction: column; }
|
|
||||||
.product-section .product-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 20px;
|
|
||||||
margin-bottom: 40px;
|
|
||||||
position: relative;
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
!* 2. 제품 이미지 기본 스타일 *!
|
|
||||||
.product-img {
|
|
||||||
width: 200px;
|
|
||||||
height: 200px;
|
|
||||||
overflow: visible;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.product-img img {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
object-fit: cover;
|
|
||||||
border-radius: 12px;
|
|
||||||
transition: all 0.4s ease;
|
|
||||||
box-shadow: 0 4px 15px rgba(0,0,0,0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
!* 💡 [모드 1] 메인 영역 내부 중앙 팝업 *!
|
|
||||||
#active-popup-img {
|
|
||||||
position: absolute !important;
|
|
||||||
top: 50% !important;
|
|
||||||
left: 50% !important;
|
|
||||||
!* 시작 상태: 작고 투명하게 *!
|
|
||||||
transform: translate(-50%, -50%) scale(0.1) !important;
|
|
||||||
width: calc(100% - 40px) !important; !* 사방 20px 마진 *!
|
|
||||||
height: calc(100% - 40px) !important;
|
|
||||||
max-width: 1560px;
|
|
||||||
z-index: 9999 !important;
|
|
||||||
box-shadow: 0 40px 100px rgba(0,0,0,0.8);
|
|
||||||
border: 3px solid rgba(255,255,255,0.5);
|
|
||||||
object-fit: contain !important;
|
|
||||||
opacity: 0;
|
|
||||||
transition: transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.3s ease;
|
|
||||||
!* 💡 [핵심] 마우스 이벤트를 무시하여 아이템 mouseleave 방해 금지 *!
|
|
||||||
pointer-events: none !important;
|
|
||||||
}
|
|
||||||
!* 활성화 상태: 정중앙 100% 크기 *!
|
|
||||||
#active-popup-img.active {
|
|
||||||
transform: translate(-50%, -50%) scale(1) !important;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
!* 💡 [모드 2] 점선 연결선 *!
|
|
||||||
.show-connector::after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
border-top: 3px dashed #ffd200;
|
|
||||||
z-index: 500;
|
|
||||||
pointer-events: none;
|
|
||||||
width: 0 !important; !* 시작은 길이 0 *!
|
|
||||||
transform: rotate(var(--line-angle, 0deg)) !important;
|
|
||||||
transform-origin: left center !important;
|
|
||||||
transition: width 0.5s ease;
|
|
||||||
display: block !important;
|
|
||||||
}
|
|
||||||
!* 활성화 상태: 계산된 길이만큼 뻗어나감 *!
|
|
||||||
.show-connector.active::after {
|
|
||||||
width: var(--line-width, 0px) !important;
|
|
||||||
animation: dash-move 1.5s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
!* 방향별 연결선 시작 위치 *!
|
|
||||||
.product-side.left .show-connector::after { left: 100% !important; margin-left: 10px; }
|
|
||||||
.product-side.right .show-connector::after {
|
|
||||||
left: 0 !important;
|
|
||||||
margin-right: 10px;
|
|
||||||
transform-origin: right center !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes dash-move { to { stroke-dashoffset: -20; } }
|
|
||||||
|
|
||||||
!* 3. 메인 이미지 및 블루 스폿 설정 *!
|
|
||||||
.product-main {
|
|
||||||
position: relative;
|
|
||||||
width: 1600px;
|
|
||||||
height: 1200px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.product-main img { width: 100%; height: 100%; object-fit: cover; }
|
|
||||||
|
|
||||||
.product-hotspot {
|
|
||||||
position: absolute !important;
|
|
||||||
width: 45px !important;
|
|
||||||
height: 45px !important;
|
|
||||||
background: rgba(0, 123, 255, 0.8) !important;
|
|
||||||
border: 3px solid #fff !important;
|
|
||||||
border-radius: 50% !important;
|
|
||||||
transform: translate(-50%, -50%) !important;
|
|
||||||
z-index: 500;
|
|
||||||
display: none;
|
|
||||||
animation: hotspot-pulse-blue 1.5s infinite;
|
|
||||||
}
|
|
||||||
@keyframes hotspot-pulse-blue {
|
|
||||||
0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.8; }
|
|
||||||
50% { transform: translate(-50%, -50%) scale(1.4); opacity: 1; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.product-hotspot::after {
|
|
||||||
content: ''; position: absolute; top: 50%; left: 50%; width: 100%; height: 100%;
|
|
||||||
background-color: rgba(0, 123, 255, 0.3); border-radius: 50%;
|
|
||||||
transform: translate(-50%, -50%); animation: hotspot-ring 1.5s infinite;
|
|
||||||
}
|
|
||||||
@keyframes hotspot-ring {
|
|
||||||
0% { width: 45px; height: 45px; opacity: 0.5; }
|
|
||||||
100% { width: 120px; height: 120px; opacity: 0; }
|
|
||||||
}*/
|
|
||||||
/*
|
|
||||||
!* ============================================================
|
|
||||||
[최종 통합본] 메인 맵 전용 스타일 (products2.css)
|
|
||||||
============================================================ *!
|
|
||||||
|
|
||||||
!* 1. 컨테이너 및 레이아웃 *!
|
|
||||||
.product-section { display: flex; justify-content: center; align-items: flex-start; gap: 40px; padding: 40px 20px; }
|
|
||||||
.product-section .product-side { flex-direction: column; }
|
|
||||||
.product-section .product-item { display: flex; align-items: center; gap: 20px; margin-bottom: 40px; position: relative; z-index: 10; }
|
|
||||||
|
|
||||||
!* 2. 제품 이미지 기본 스타일 *!
|
|
||||||
.product-img { width: 200px; height: 200px; overflow: visible; position: relative; }
|
|
||||||
.product-img img { width: 100%; height: 100%; object-fit: cover; border-radius: 12px; transition: all 0.4s ease; box-shadow: 0 4px 15px rgba(0,0,0,0.3); }
|
|
||||||
|
|
||||||
!* 💡 [모드 1] 메인 영역(.product-main) 내부 중앙 팝업 *!
|
|
||||||
#active-popup-img {
|
|
||||||
position: absolute !important;
|
|
||||||
top: 50% !important; left: 50% !important;
|
|
||||||
transform: translate(-50%, -50%) !important;
|
|
||||||
width: calc(100% - 40px) !important; !* 💡 부모 내부 20px 마진 *!
|
|
||||||
height: calc(100% - 40px) !important;
|
|
||||||
max-width: 1560px;
|
|
||||||
z-index: 9999 !important;
|
|
||||||
box-shadow: 0 40px 100px rgba(0,0,0,0.8);
|
|
||||||
border: 3px solid rgba(255,255,255,0.5);
|
|
||||||
object-fit: contain !important;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
!* 💡 [모드 2] 점선 연결선 *!
|
|
||||||
.show-connector::after {
|
|
||||||
content: ''; position: absolute; top: 50%;
|
|
||||||
border-top: 3px dashed #ffd200; z-index: 500; pointer-events: none;
|
|
||||||
width: var(--line-width, 0px) !important;
|
|
||||||
transform: rotate(var(--line-angle, 0deg)) !important;
|
|
||||||
transform-origin: left center !important;
|
|
||||||
display: block !important;
|
|
||||||
}
|
|
||||||
.product-side.left .show-connector::after { left: 100% !important; margin-left: 10px; }
|
|
||||||
.product-side.right .show-connector::after { left: 0 !important; margin-right: 10px; transform-origin: right center !important; }
|
|
||||||
|
|
||||||
@keyframes dash-move { to { stroke-dashoffset: -20; } }
|
|
||||||
|
|
||||||
!* 3. 메인 이미지 및 블루 스폿 설정 *!
|
|
||||||
.product-main { position: relative; width: 1600px; height: 1200px; flex-shrink: 0; overflow: hidden; }
|
|
||||||
.product-main img { width: 100%; height: 100%; object-fit: cover; }
|
|
||||||
|
|
||||||
.product-hotspot {
|
|
||||||
position: absolute !important; width: 45px !important; height: 45px !important;
|
|
||||||
background: rgba(0, 123, 255, 0.8) !important; border: 3px solid #fff !important;
|
|
||||||
border-radius: 50% !important; transform: translate(-50%, -50%) !important;
|
|
||||||
z-index: 500; display: none; animation: hotspot-pulse-blue 1.5s infinite;
|
|
||||||
}
|
|
||||||
@keyframes hotspot-pulse-blue { 0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.8; } 50% { transform: translate(-50%, -50%) scale(1.4); opacity: 1; } }
|
|
||||||
|
|
||||||
.product-hotspot::after {
|
|
||||||
content: ''; position: absolute; top: 50%; left: 50%; width: 100%; height: 100%;
|
|
||||||
background-color: rgba(0, 123, 255, 0.3); border-radius: 50%;
|
|
||||||
transform: translate(-50%, -50%); animation: hotspot-ring 1.5s infinite;
|
|
||||||
}
|
|
||||||
@keyframes hotspot-ring { 0% { width: 45px; height: 45px; opacity: 0.5; } 100% { width: 120px; height: 120px; opacity: 0; } }
|
|
||||||
|
|
||||||
!* 💡 [모드 1] 메인 영역(.product-main) 내부 중앙 팝업 *!
|
|
||||||
#active-popup-img {
|
|
||||||
position: absolute !important;
|
|
||||||
top: 50% !important;
|
|
||||||
left: 50% !important;
|
|
||||||
transform: translate(-50%, -50%) scale(0.1) !important; !* 💡 초기 크기를 작게 시작 *!
|
|
||||||
width: calc(100% - 40px) !important; !* 메인 영역 너비의 90% *!
|
|
||||||
height: auto !important;
|
|
||||||
max-height: 90% !important;
|
|
||||||
z-index: 9999 !important;
|
|
||||||
box-shadow: 0 40px 100px rgba(0,0,0,0.8);
|
|
||||||
border: 3px solid rgba(255,255,255,0.5);
|
|
||||||
object-fit: contain !important;
|
|
||||||
pointer-events: none;
|
|
||||||
opacity: 0; !* 💡 초기 투명도 *!
|
|
||||||
transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.3s ease; !* 💡 애니메이션 추가 *!
|
|
||||||
}
|
|
||||||
|
|
||||||
!* 💡 [추가] 팝업이 활성화될 때 최종 크기로 *!
|
|
||||||
.product-section .product-main #active-popup-img.active {
|
|
||||||
transform: translate(-50%, -50%) scale(1) !important; !* 💡 최종 크기 *!
|
|
||||||
opacity: 1; !* 💡 최종 투명도 *!
|
|
||||||
}*/
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
@import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css');
|
|
||||||
|
|
||||||
/* --- [유지] 기본 및 공통 설정 --- */
|
|
||||||
.products-main-page { background-color: #0b0f1a; font-family: 'Pretendard', sans-serif; margin: 0; padding: 0; }
|
|
||||||
.main-container { width: 100%; overflow: hidden; }
|
|
||||||
.container { max-width: 1600px; margin: 0 auto; padding: 0 15px; box-sizing: border-box; }
|
|
||||||
.section-title { text-align: center; margin-bottom: 50px; }
|
|
||||||
.section-title h3 { font-size: 32px; font-weight: 700; color: #333; margin-bottom: 15px; position: relative; display: inline-block; }
|
|
||||||
.section-title h3::after { content: ''; display: block; width: 40px; height: 2px; background: #0054a6; margin: 15px auto 0; }
|
|
||||||
.section-title p { font-size: 16px; color: #666; }
|
|
||||||
|
|
||||||
/* --- [유지] 메인 비주얼 슬라이더 관련 (기존 소스) --- */
|
|
||||||
.main-visual { width: 100%; height: auto; position: relative; padding-top: 190px; box-sizing: border-box; }
|
|
||||||
.visual-slider, .swiper-wrapper, .swiper-slide { height: 100%; }
|
|
||||||
.visual-link { display: block; width: 100%; height: 100%; position: relative; }
|
|
||||||
.visual-img { width: 100%; height: 100%; background-size: cover; background-position: center; position: absolute; top: 0; left: 0; z-index: 1; }
|
|
||||||
.visual-layer-wrap { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; z-index: 2; text-align: center; color: #fff; text-shadow: 2px 2px 8px rgba(0,0,0,0.5); }
|
|
||||||
.visual-title { font-size: 48px; font-weight: 700; color: #ffd200; margin: 0; }
|
|
||||||
.visual-divider { display: block; width: 50px; height: 2px; background-color: rgba(255, 255, 255, 0.5); margin: 30px auto; }
|
|
||||||
.visual-subtitle { font-size: 24px; font-weight: 500; line-height: 1.6; margin: 0; }
|
|
||||||
.main-visual .swiper-button-next, .main-visual .swiper-button-prev { width: 70px; height: 70px; background-color: rgba(0, 0, 0, 0.1); border-radius: 50%; color: #fff; position: absolute; top: calc(50% + 45px); transform: translateY(-50%); z-index: 10; display: flex; justify-content: center; align-items: center; cursor: pointer; }
|
|
||||||
.main-visual .swiper-button-prev { left: 20px; }
|
|
||||||
.main-visual .swiper-button-next { right: 20px; }
|
|
||||||
|
|
||||||
/* --- [유지] 히어로 섹션 관련 (기존 소스) --- */
|
|
||||||
.hero_container { padding: 120px 0 80px 0; background: #fff; }
|
|
||||||
.hero_container .text_area { position: relative; width: 100%; max-width: 1600px; padding: 0 20px; text-align: left; color: #111; line-height: 1.6; z-index: 2; }
|
|
||||||
/* ... (기존의 btn_box, main_title 등 생략하지만 파일에는 유지하셔야 합니다) ... */
|
|
||||||
|
|
||||||
/* --- [중요/수정] 팝업창 및 맵 전용 설정 --- */
|
|
||||||
|
|
||||||
/* 1. 최상위 섹션 기준점 (팝업 중앙 배치를 위해 필수) */
|
|
||||||
.product-map-section {
|
|
||||||
position: relative !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 2. 맵 및 핫스팟 보정 */
|
|
||||||
.map-wrapper {
|
|
||||||
position: relative; display: inline-block;
|
|
||||||
width: 1600px; overflow: hidden; border-radius: 24px;
|
|
||||||
margin: 0 auto; background: #161b26;
|
|
||||||
}
|
|
||||||
.map-container {
|
|
||||||
position: relative; width: 100%; height: 980px !important;
|
|
||||||
background-size: 100% 100% !important; cursor: crosshair;
|
|
||||||
}
|
|
||||||
.hotspot {
|
|
||||||
position: absolute; width: 22px !important; height: 22px !important;
|
|
||||||
background: rgba(59, 130, 246, 0.6); border: 2px solid #fff; border-radius: 50%;
|
|
||||||
transform: translate(-50%, -50%) !important; /* 💡 Y축 오차 해결 */
|
|
||||||
z-index: 10; cursor: pointer;
|
|
||||||
}
|
|
||||||
.hotspot::after { content: ''; position: absolute; top: 50%; left: 50%; width: 100%; height: 100%; background-color: rgba(0, 123, 255, 0.4); border-radius: 50%; transform: translate(-50%, -50%); animation: hotspot-pulse 2s infinite; }
|
|
||||||
@keyframes hotspot-pulse { 0% { width: 20px; height: 20px; opacity: 0.8; } 100% { width: 60px; height: 60px; opacity: 0; } }
|
|
||||||
|
|
||||||
/* 3. [최종] 팝업 통합 스타일 (중복 완전 제거) */
|
|
||||||
#hover-preview {
|
|
||||||
position: absolute !important; /* 💡 섹션 내 중앙 배치 */
|
|
||||||
left: 50% !important;
|
|
||||||
top: 50% !important;
|
|
||||||
transform: translate(-50%, -50%) !important;
|
|
||||||
|
|
||||||
display: none;
|
|
||||||
z-index: 1000;
|
|
||||||
background: rgba(15, 23, 42, 0.98) !important;
|
|
||||||
backdrop-filter: blur(20px);
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.15);
|
|
||||||
border-radius: 24px;
|
|
||||||
padding: 30px !important;
|
|
||||||
box-shadow: 0 50px 100px -20px rgba(0, 0, 0, 0.9);
|
|
||||||
|
|
||||||
/* 💡 사방 20px 마진 강제 */
|
|
||||||
max-width: calc(100% - 40px) !important;
|
|
||||||
max-height: calc(100% - 40px) !important;
|
|
||||||
width: 500px; /* 호버 시 기본 너비 */
|
|
||||||
transition: width 0.3s ease;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 클릭 고정 시 */
|
|
||||||
#hover-preview.fixed-mode {
|
|
||||||
display: flex !important;
|
|
||||||
flex-direction: column !important; /* 💡 세로 배치를 강제하여 옆으로 벌어짐 해결 */
|
|
||||||
width: calc(100% - 40px) !important;
|
|
||||||
height: calc(100% - 40px) !important;
|
|
||||||
pointer-events: auto !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 4. 제품 그리드 및 아이템 레이아웃 */
|
|
||||||
.products-grid {
|
|
||||||
display: grid !important;
|
|
||||||
grid-template-columns: repeat(2, 1fr) !important;
|
|
||||||
gap: 20px;
|
|
||||||
flex: 1;
|
|
||||||
overflow-y: auto;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.products-grid.single-item, .products-grid.full-html-mode {
|
|
||||||
grid-template-columns: 1fr !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 모든 아이템은 세로 정렬 */
|
|
||||||
.product-item.item-vertical {
|
|
||||||
display: flex !important;
|
|
||||||
flex-direction: column !important;
|
|
||||||
align-items: flex-start !important;
|
|
||||||
background: rgba(255, 255, 255, 0.05) !important;
|
|
||||||
padding: 20px;
|
|
||||||
border-radius: 16px;
|
|
||||||
color: #fff;
|
|
||||||
text-align: left !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.product-img-box { width: 100% !important; height: auto !important; max-height: 400px; background: #000; border-radius: 12px; overflow: hidden; display: flex; align-items: center; justify-content: center; margin-bottom: 15px; }
|
|
||||||
.product-img-box img { width: 100%; height: 100%; object-fit: contain; }
|
|
||||||
|
|
||||||
/* 5. 에디터 뷰 최적화 */
|
|
||||||
.editor-content-view { width: 100% !important; color: #eee !important; line-height: 1.7; margin-bottom: 20px; }
|
|
||||||
.editor-content-view img { max-width: 100% !important; width: auto !important; height: auto !important; display: block; margin: 15px auto; border-radius: 10px; }
|
|
||||||
|
|
||||||
/* 스크롤바 디자인 */
|
|
||||||
#preview-grid::-webkit-scrollbar { width: 6px; }
|
|
||||||
#preview-grid::-webkit-scrollbar-thumb { background: rgba(59, 130, 246, 0.5); border-radius: 10px; }
|
|
||||||
.content-divider { border: 0; border-top: 1px solid rgba(255,255,255,0.1); margin: 30px 0; }
|
|
||||||
|
Before Width: | Height: | Size: 28 MiB |
|
Before Width: | Height: | Size: 15 MiB |
|
Before Width: | Height: | Size: 12 MiB |
|
Before Width: | Height: | Size: 16 MiB |
|
Before Width: | Height: | Size: 8.9 MiB |
|
Before Width: | Height: | Size: 11 MiB |
|
Before Width: | Height: | Size: 15 MiB |
|
Before Width: | Height: | Size: 11 MiB |
|
Before Width: | Height: | Size: 25 MiB |
|
Before Width: | Height: | Size: 14 MiB |
|
Before Width: | Height: | Size: 4.1 MiB |
|
Before Width: | Height: | Size: 185 KiB After Width: | Height: | Size: 1.8 MiB |
|
Before Width: | Height: | Size: 238 KiB |
@@ -3,7 +3,7 @@ if (!defined('_GNUBOARD_')) exit;
|
|||||||
$skin_url = G5_THEME_URL . '/rb.layout/dnssash_main';
|
$skin_url = G5_THEME_URL . '/rb.layout/dnssash_main';
|
||||||
$today = G5_TIME_YMD;
|
$today = G5_TIME_YMD;
|
||||||
|
|
||||||
function process_product_positions(&$db_products, $main_visual_data) {
|
/*function process_product_positions(&$db_products, $main_visual_data) {
|
||||||
if (empty($db_products)) return;
|
if (empty($db_products)) return;
|
||||||
|
|
||||||
foreach ($db_products as &$product) {
|
foreach ($db_products as &$product) {
|
||||||
@@ -21,8 +21,54 @@ function process_product_positions(&$db_products, $main_visual_data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
unset($product);
|
unset($product);
|
||||||
}
|
}*/
|
||||||
|
function process_product_positions(&$db_products, $main_visual_data) {
|
||||||
|
if (empty($db_products)) return;
|
||||||
|
|
||||||
|
// 1. $db_products를 title을 키로 하는 맵으로 변환하여 빠른 조회를 가능하게 합니다.
|
||||||
|
$db_products_map = [];
|
||||||
|
foreach ($db_products as $product) {
|
||||||
|
$db_products_map[$product['title']] = $product;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ordered_products = [];
|
||||||
|
|
||||||
|
// 2. $main_visual_data의 순서에 따라 제품을 정렬하고 속성을 업데이트합니다.
|
||||||
|
foreach ($main_visual_data as $main_item) {
|
||||||
|
$title = $main_item['title'];
|
||||||
|
if (isset($db_products_map[$title])) {
|
||||||
|
$product = $db_products_map[$title];
|
||||||
|
|
||||||
|
// 기존 로직: pos 및 img_url 업데이트
|
||||||
|
if (isset($main_item['pos'])) {
|
||||||
|
$product['pos'] = $main_item['pos'];
|
||||||
|
}
|
||||||
|
if (isset($main_item['img_url'])) {
|
||||||
|
$product['img_url'] = $main_item['img_url'];
|
||||||
|
}
|
||||||
|
// main_visual_data에 xPct, yPct가 있다면 db_products의 값보다 우선합니다.
|
||||||
|
// if (isset($main_item['xPct'])) {
|
||||||
|
// $product['xPct'] = $main_item['xPct'];
|
||||||
|
// }
|
||||||
|
// if (isset($main_item['yPct'])) {
|
||||||
|
// $product['yPct'] = $main_item['yPct'];
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
$ordered_products[] = $product;
|
||||||
|
unset($db_products_map[$title]); // 처리된 항목은 맵에서 제거합니다.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. $main_visual_data에 포함되지 않은 나머지 제품들을 뒤에 추가합니다.
|
||||||
|
foreach ($db_products_map as $remaining_product) {
|
||||||
|
$ordered_products[] = $remaining_product;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 원본 $db_products 배열을 새로 정렬된 배열로 교체합니다.
|
||||||
|
$db_products = $ordered_products;
|
||||||
|
unset($product);
|
||||||
|
}
|
||||||
// 1. 게시판 데이터 로드 시도
|
// 1. 게시판 데이터 로드 시도
|
||||||
$bo_table = 'bconstruction'; // 게시판 ID
|
$bo_table = 'bconstruction'; // 게시판 ID
|
||||||
$sql = " select * from {$g5['write_prefix']}$bo_table
|
$sql = " select * from {$g5['write_prefix']}$bo_table
|
||||||
@@ -32,20 +78,22 @@ $sql = " select * from {$g5['write_prefix']}$bo_table
|
|||||||
$result = sql_query($sql);
|
$result = sql_query($sql);
|
||||||
|
|
||||||
$db_products = array();
|
$db_products = array();
|
||||||
$main_visual_product_data = [
|
|
||||||
["title" => "입면분할창","pos"=>"left", "page" => "20p", "desc" => "조망권과 환기를 극대화한 시스템", "img_url" => $skin_url . '/images/1.webp', 'xPct'=> 63.0, 'yPct'=> 24.0],
|
|
||||||
["title" => "프로젝트창","pos"=>"left", "page" => "48p", "desc" => "기밀성이 우수한 상부 개폐식 창호", "img_url" => $skin_url . '/images/2' . '.webp', "xPct" => 71.0, "yPct" => 30.3],
|
|
||||||
["title" => "소형단창,이중창","pos"=>"left", "page" => "36p", "desc" => "침실 소형 전용 슬라이딩 창호", "img_url" => $skin_url . '/images/3' . '.webp', "xPct" => 80.7, "yPct" => 43.6],
|
|
||||||
["title" => "학교창","pos"=>"left", "page" => "40p", "desc" => "안전 기능이 강화된 환기창", "img_url" => $skin_url . '/images/5' . '.webp', "xPct" => 78.7, "yPct" => 41.4],
|
|
||||||
["title" => "판넬창", "pos"=>"left","page" => "44p", "desc" => "벽체 마감용 내구성 우수 창호", "img_url" => $skin_url . '/images/4' . '.webp', "xPct" => 5.7, "yPct" => 91.4],
|
|
||||||
|
|
||||||
["title" => "대형단창","pos"=>"right", "page" => "32p", "desc" => "발코니 전용 단열 슬라이딩 단창", "img_url" => $skin_url . '/images/6' . '.webp', "xPct" => 25.6, "yPct" => 36.0],
|
$main_visual_product_data = [
|
||||||
["title" => "대형이중창","pos"=>"right", "page" => "28p", "desc" => "방음 및 풍압 견딤력이 우수한 이중창", "img_url" => $skin_url . '/images/7' . '.webp', "xPct" => 36.9, "yPct" => 29.8],
|
["title" => "입면분할창", "pos"=>"left", "page" => "20p", "desc" => "조망권과 환기를 극대화한 시스템", "pruimg_url" => $skin_url . '/images/1.webp',"img_url" => $skin_url . '/images/1.webp', 'xPct'=> 46.4, 'yPct'=> 12.5],
|
||||||
["title" => "스마트 발코니 전용창","pos"=>"right", "page" => "12p", "desc" => "외창 전용 고기밀 샷시", "img_url" => $skin_url . '/images/8' . '.webp', "xPct" => 23.0, "yPct" => 37.8],
|
["title" => "프로젝트창","pos"=>"left", "page" => "48p", "desc" => "기밀성이 우수한 상부 개폐식 창호", "pruimg_url" => $skin_url . '/images/2.webp',"img_url" => $skin_url . '/images/2' . '.webp', "xPct" => 25.4, "yPct" => 24.8],
|
||||||
["title" => "스마트 이중창","pos"=>"right", "page" => "24p", "desc" => "보안이 강화된 자동잠금 이중창", "img_url" => $skin_url . '/images/9' . '.webp', "xPct" => 46.7, "yPct" => 22.8],
|
["title" => "소형단창","pos"=>"left", "page" => "36p", "desc" => "침실 소형 전용 슬라이딩 창호", "pruimg_url" => $skin_url . '/images/3.webp',"img_url" => $skin_url . '/images/3' . '.webp', "xPct" => 7.6, "yPct" => 33.0],
|
||||||
["title" => "발코니 확장 이중창","pos"=>"right", "page" => "16p", "desc" => "거실 확장용 고단열 이중창", "img_url" => $skin_url . '/images/10' . '.webp', "xPct" => 50.4, "yPct" => 20.8],
|
["title" => "학교창","pos"=>"left", "page" => "40p", "desc" => "안전 기능이 강화된 환기창", "pruimg_url" => $skin_url . '/images/5.webp',"img_url" => $skin_url . '/images/5' . '.webp' ],
|
||||||
|
["title" => "판넬창", "pos"=>"left", "page" => "44p", "desc" => "벽체 마감용 내구성 우수 창호", "pruimg_url" => $skin_url . '/images/4.webp',"img_url" => $skin_url . '/images/4' . '.webp'],
|
||||||
|
|
||||||
|
["title" => "대형단창","pos"=>"right", "page" => "32p", "desc" => "발코니 전용 단열 슬라이딩 단창", "pruimg_url" => $skin_url . '/images/6.webp',"img_url" => $skin_url . '/images/6' . '.webp', "xPct" => 62.1, "yPct" => 16.1],
|
||||||
|
["title" => "대형이중창","pos"=>"right", "page" => "28p", "desc" => "방음 및 풍압 견딤력이 우수한 이중창","pruimg_url" => $skin_url . '/images/7.webp', "img_url" => $skin_url . '/images/7' . '.webp', "xPct" => 62.1, "yPct" => 16.1],
|
||||||
|
["title" => "스마트 발코니 전용창","pos"=>"right", "page" => "12p", "desc" => "외창 전용 고기밀 샷시","pruimg_url" => $skin_url . '/images/8.webp', "img_url" => $skin_url . '/images/8' . '.webp', "xPct" => 62.1, "yPct" => 16.1],
|
||||||
|
["title" => "스마트 이중창","pos"=>"right", "right" => "24p", "desc" => "보안이 강화된 자동잠금 이중창","pruimg_url" => $skin_url . '/images/9.webp', "img_url" => $skin_url . '/images/9' . '.webp', "xPct" => 93.5, "yPct" => 41.6],
|
||||||
|
["title" => "발코니 확장 이중창","pos"=>"right", "page" => "16p", "desc" => "거실 확장용 고단열 이중창","pruimg_url" => $skin_url . '/images/10.webp', "img_url" => $skin_url . '/images/10' . '.webp', "xPct" => 93.5, "yPct" => 41.6],
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
while($row = sql_fetch_array($result)) {
|
while($row = sql_fetch_array($result)) {
|
||||||
|
|
||||||
|
|
||||||
@@ -78,21 +126,20 @@ while($row = sql_fetch_array($result)) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
//$db_products =null;
|
|
||||||
|
|
||||||
if (empty($db_products)) {
|
if (empty($db_products)) {
|
||||||
$db_products = [
|
$db_products = [
|
||||||
["title" => "입면분할창", "pos"=>"left", "page" => "20p", "desc" => "조망권과 환기를 극대화한 시스템", "pruimg_url" => $skin_url . '/images/1.webp',"img_url" => $skin_url . '/images/1.webp', 'xPct'=> 63.0, 'yPct'=> 24.0,],
|
["title" => "입면분할창", "pos"=>"left", "page" => "20p", "desc" => "조망권과 환기를 극대화한 시스템", "pruimg_url" => $skin_url . '/images/1.webp',"img_url" => $skin_url . '/images/1.webp', 'xPct'=> 46.4, 'yPct'=> 12.5],
|
||||||
["title" => "프로젝트창","pos"=>"left", "page" => "48p", "desc" => "기밀성이 우수한 상부 개폐식 창호", "pruimg_url" => $skin_url . '/images/2.webp',"img_url" => $skin_url . '/images/2' . '.webp', "xPct" => 71.0, "yPct" => 30.3],
|
["title" => "프로젝트창","pos"=>"left", "page" => "48p", "desc" => "기밀성이 우수한 상부 개폐식 창호", "pruimg_url" => $skin_url . '/images/2.webp',"img_url" => $skin_url . '/images/2' . '.webp', "xPct" => 25.4, "yPct" => 24.8],
|
||||||
["title" => "소형단창,이중창","pos"=>"left", "page" => "36p", "desc" => "침실 소형 전용 슬라이딩 창호", "pruimg_url" => $skin_url . '/images/3.webp',"img_url" => $skin_url . '/images/3' . '.webp', "xPct" => 80.7, "yPct" => 43.6],
|
["title" => "소형단창","pos"=>"left", "page" => "36p", "desc" => "침실 소형 전용 슬라이딩 창호", "pruimg_url" => $skin_url . '/images/3.webp',"img_url" => $skin_url . '/images/3' . '.webp', "xPct" => 7.6, "yPct" => 33.0],
|
||||||
["title" => "학교창","pos"=>"left", "page" => "40p", "desc" => "안전 기능이 강화된 환기창", "pruimg_url" => $skin_url . '/images/5.webp',"img_url" => $skin_url . '/images/5' . '.webp', "xPct" => 78.7, "yPct" => 41.4],
|
["title" => "학교창","pos"=>"left", "page" => "40p", "desc" => "안전 기능이 강화된 환기창", "pruimg_url" => $skin_url . '/images/5.webp',"img_url" => $skin_url . '/images/5' . '.webp' ],
|
||||||
["title" => "판넬창", "pos"=>"left", "page" => "44p", "desc" => "벽체 마감용 내구성 우수 창호", "pruimg_url" => $skin_url . '/images/4.webp',"img_url" => $skin_url . '/images/4' . '.webp', "xPct" => 5.7, "yPct" => 91.4],
|
["title" => "판넬창", "pos"=>"left", "page" => "44p", "desc" => "벽체 마감용 내구성 우수 창호", "pruimg_url" => $skin_url . '/images/4.webp',"img_url" => $skin_url . '/images/4' . '.webp'],
|
||||||
|
|
||||||
["title" => "대형단창","pos"=>"right", "page" => "32p", "desc" => "발코니 전용 단열 슬라이딩 단창", "pruimg_url" => $skin_url . '/images/6.webp',"img_url" => $skin_url . '/images/6' . '.webp', "xPct" => 25.6, "yPct" => 36.0],
|
["title" => "대형단창","pos"=>"right", "page" => "32p", "desc" => "발코니 전용 단열 슬라이딩 단창", "pruimg_url" => $skin_url . '/images/6.webp',"img_url" => $skin_url . '/images/6' . '.webp', "xPct" => 62.1, "yPct" => 16.1],
|
||||||
["title" => "대형이중창","pos"=>"right", "page" => "28p", "desc" => "방음 및 풍압 견딤력이 우수한 이중창","pruimg_url" => $skin_url . '/images/7.webp', "img_url" => $skin_url . '/images/7' . '.webp', "xPct" => 36.9, "yPct" => 29.8],
|
["title" => "대형이중창","pos"=>"right", "page" => "28p", "desc" => "방음 및 풍압 견딤력이 우수한 이중창","pruimg_url" => $skin_url . '/images/7.webp', "img_url" => $skin_url . '/images/7' . '.webp', "xPct" => 62.1, "yPct" => 16.1],
|
||||||
["title" => "스마트 발코니 전용창","pos"=>"right", "page" => "12p", "desc" => "외창 전용 고기밀 샷시","pruimg_url" => $skin_url . '/images/8.webp', "img_url" => $skin_url . '/images/8' . '.webp', "xPct" => 23.0, "yPct" => 37.8],
|
["title" => "스마트 발코니 전용창","pos"=>"right", "page" => "12p", "desc" => "외창 전용 고기밀 샷시","pruimg_url" => $skin_url . '/images/8.webp', "img_url" => $skin_url . '/images/8' . '.webp', "xPct" => 62.1, "yPct" => 16.1],
|
||||||
["title" => "스마트 이중창","pos"=>"right", "right" => "24p", "desc" => "보안이 강화된 자동잠금 이중창","pruimg_url" => $skin_url . '/images/9.webp', "img_url" => $skin_url . '/images/9' . '.webp', "xPct" => 46.7, "yPct" => 22.8],
|
["title" => "스마트 이중창","pos"=>"right", "right" => "24p", "desc" => "보안이 강화된 자동잠금 이중창","pruimg_url" => $skin_url . '/images/9.webp', "img_url" => $skin_url . '/images/9' . '.webp', "xPct" => 93.5, "yPct" => 41.6],
|
||||||
["title" => "발코니 확장 이중창","pos"=>"right", "page" => "16p", "desc" => "거실 확장용 고단열 이중창","pruimg_url" => $skin_url . '/images/10.webp', "img_url" => $skin_url . '/images/10' . '.webp', "xPct" => 50.4, "yPct" => 20.8],
|
["title" => "발코니 확장 이중창","pos"=>"right", "page" => "16p", "desc" => "거실 확장용 고단열 이중창","pruimg_url" => $skin_url . '/images/10.webp', "img_url" => $skin_url . '/images/10' . '.webp', "xPct" => 93.5, "yPct" => 41.6],
|
||||||
|
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
@@ -119,6 +166,9 @@ function render_product_side($db_products, $side) {
|
|||||||
data-x1="'.$item['xPct'].'"
|
data-x1="'.$item['xPct'].'"
|
||||||
data-y1="'.$item['yPct'].'"
|
data-y1="'.$item['yPct'].'"
|
||||||
data-img="'.$item['pruimg_url'].'"
|
data-img="'.$item['pruimg_url'].'"
|
||||||
|
data-title="'.htmlspecialchars($item['title']).'"
|
||||||
|
data-desc="'.htmlspecialchars($item['desc']).'"
|
||||||
|
data-content="'.htmlspecialchars(isset($item['content']) ? $item['content'] : "").'"
|
||||||
'.$link_attr.'>
|
'.$link_attr.'>
|
||||||
<div class="product-img">
|
<div class="product-img">
|
||||||
<img src="'.$item['img_url'].'" alt="'.htmlspecialchars($item['title']).'">
|
<img src="'.$item['img_url'].'" alt="'.htmlspecialchars($item['title']).'">
|
||||||
@@ -160,8 +210,11 @@ add_stylesheet('<link rel="stylesheet" href="'.G5_THEME_URL.'/rb.layout/'.$rb_co
|
|||||||
//add_stylesheet('<link rel="stylesheet" href="'.G5_THEME_URL.'/rb.layout/'.$rb_core['layout'].'/css/style.css?ver='.G5_CSS_VER.'">', 0);
|
//add_stylesheet('<link rel="stylesheet" href="'.G5_THEME_URL.'/rb.layout/'.$rb_core['layout'].'/css/style.css?ver='.G5_CSS_VER.'">', 0);
|
||||||
add_stylesheet('<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css" />', 0);
|
add_stylesheet('<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css" />', 0);
|
||||||
add_javascript('<script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>', 0);
|
add_javascript('<script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>', 0);
|
||||||
//add_javascript('<script src="'.G5_THEME_URL.'/rb.layout/'.$rb_core['layout'].'/js/products.js?ver='.G5_CSS_VER.'"></script>', 0);
|
add_javascript('<script src="'.G5_THEME_URL.'/rb.layout/'.$rb_core['layout'].'/js/products.js?ver='.G5_CSS_VER.'"></script>', 0);
|
||||||
add_javascript('<script src="'.G5_THEME_URL.'/rb.layout/'.$rb_core['layout'].'/js/products2.js?ver='.G5_CSS_VER.'"></script>', 0);
|
add_javascript('<script src="'.G5_THEME_URL.'/rb.layout/'.$rb_core['layout'].'/js/products2.js?ver='.G5_CSS_VER.'"></script>', 0);
|
||||||
|
// JS 추가 (GSAP 라이브러리를 먼저 로드하고, 그 뒤에 custom.js를 로드)
|
||||||
|
add_javascript('<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>', 0);
|
||||||
|
|
||||||
include_once(G5_ADMIN_PATH . '/order_manage/components/_expert_visit_popups.php');
|
include_once(G5_ADMIN_PATH . '/order_manage/components/_expert_visit_popups.php');
|
||||||
?>
|
?>
|
||||||
<div class="main-container">
|
<div class="main-container">
|
||||||
@@ -211,11 +264,18 @@ include_once(G5_ADMIN_PATH . '/order_manage/components/_expert_visit_popups.php'
|
|||||||
<?php echo render_product_side( $db_products, 'left');?>
|
<?php echo render_product_side( $db_products, 'left');?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="product-main">
|
<div class="product-main" >
|
||||||
<img src='<?php echo $skin_url?>/images/main.webp' alt="메인 사진">
|
<img id="main-map" src='<?php echo $skin_url?>/images/main.png' alt="메인 사진">
|
||||||
<div class="product-hotspot"></div>
|
<div class="product-hotspot"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="popup-box" style="position:absolute; width:0; height:0; display:none; overflow:hidden; z-index:100; box-shadow:0 10px 30px rgba(0,0,0,0.3);">
|
||||||
|
|
||||||
|
<div class="content" >
|
||||||
|
팝업 내용
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="product-side right">
|
<div class="product-side right">
|
||||||
<?php echo render_product_side( $db_products, 'right');?>
|
<?php echo render_product_side( $db_products, 'right');?>
|
||||||
</div>
|
</div>
|
||||||
@@ -224,7 +284,7 @@ include_once(G5_ADMIN_PATH . '/order_manage/components/_expert_visit_popups.php'
|
|||||||
<div class="main-container">
|
<div class="main-container">
|
||||||
|
|
||||||
<div class="main-visual">
|
<div class="main-visual">
|
||||||
<section class="process-section">
|
<!-- <section class="process-section">-->
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<main class="layout-main-content1">
|
<main class="layout-main-content1">
|
||||||
|
|
||||||
@@ -258,60 +318,67 @@ include_once(G5_ADMIN_PATH . '/order_manage/components/_expert_visit_popups.php'
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
<!-- </section>-->
|
||||||
<section class="min-h-screen flex flex-col items-center justify-center p-6">
|
|
||||||
<div class="mb-10 text-center">
|
|
||||||
<h1 class="text-3xl md:text-4xl font-bold text-white mb-3">
|
|
||||||
고객의 공간을 완성하는 프리미엄 창호 시스템 <span class="highlight_blue">이끌림샤시</span>로 시작하세요
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<p class="text-gray-300 text-sm md:text-base max-w-2xl mx-auto leading-relaxed">
|
</div>
|
||||||
고객의 생활 공간을 고려한 설계와 정밀한 기술력으로<br>
|
</div>
|
||||||
최고의 품질과 안정적인 A/S를 제공합니다.
|
<section class="min-h-screen flex flex-col items-center justify-center p-6">
|
||||||
</p>
|
<div class="mb-10 text-center">
|
||||||
</div>
|
<h1 class="text-3xl md:text-4xl font-bold text-white mb-3">
|
||||||
|
고객의 공간을 완성하는 프리미엄 창호 시스템 <span class="highlight_blue">이끌림샤시</span>로 시작하세요
|
||||||
|
</h1>
|
||||||
|
|
||||||
<section class="hero_container">
|
<p class="text-gray-300 text-sm md::text-base max-w-2xl mx-auto leading-relaxed">
|
||||||
<div class="content_inner">
|
고객의 생활 공간을 고려한 설계와 정밀한 기술력으로<br>
|
||||||
|
최고의 품질과 안정적인 A/S를 제공합니다.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- <img src="--><?php //echo G5_THEME_URL ?><!--/rb.layout/dnssash/img/main1.png" alt="메인 배경 이미지" class="main_bg_img">-->
|
|
||||||
<div class="text_area">
|
|
||||||
<p class="label_blue">SMART WINDOW ORDERING</p>
|
|
||||||
<h1 class="main_title">
|
|
||||||
창호의 새로운 기준,<br>
|
|
||||||
<span class="highlight_blue">이끌림샤시</span>로 시작하세요
|
|
||||||
</h1>
|
|
||||||
<p class="sub_description">
|
|
||||||
복잡한 창호 교체, 이제 온라인 견적으로 투명하게.<br>
|
|
||||||
고품질 자재와 전문가의 손길을 클릭 한 번으로 만나보세요.
|
|
||||||
</p>
|
|
||||||
<!-- 전문가 상담 및 예약 버튼 (상단 오른쪽) -->
|
|
||||||
|
|
||||||
<div class="main_action_row">
|
</section>
|
||||||
<a href="<?php echo G5_BBS_URL ?>/board.php?bo_table=order" class="btn_box white" >
|
<div class="main-container">
|
||||||
<div class="btn_icon">🏢</div>
|
<!-- 1. 메인 비주얼 섹션 (클래스명 변경됨) -->
|
||||||
<div class="btn_txt">
|
<section class="map-main-visual">
|
||||||
<strong>창호 온라인 주문</strong>
|
<section class="hero_container">
|
||||||
<p>실시간 직접 견적 및 주문 확정</p>
|
<div class="content_inner">
|
||||||
</div>
|
|
||||||
</a>
|
<!-- <img src="--><?php //echo G5_THEME_URL ?><!--/rb.layout/dnssash/img/main1.png" alt="메인 배경 이미지" class="main_bg_img">-->
|
||||||
<div class="btn_box white" onclick="openExpertVisitPopup(<?php /*echo $wr_id; */?>)">
|
<div class="text_area">
|
||||||
<div class="btn_icon">👨🔧</div>
|
<p class="label_blue">SMART WINDOW ORDERING</p>
|
||||||
<div class="btn_txt">
|
<h1 class="main_title">
|
||||||
<strong>창호 전문가 부르기</strong>
|
창호의 새로운 기준,<br>
|
||||||
<p>방문 실측 및 맞춤 상담 신청</p>
|
<span class="highlight_blue">이끌림샤시</span>로 시작하세요
|
||||||
</div>
|
</h1>
|
||||||
|
<p class="sub_description">
|
||||||
|
복잡한 창호 교체, 이제 온라인 견적으로 투명하게.<br>
|
||||||
|
고품질 자재와 전문가의 손길을 클릭 한 번으로 만나보세요.
|
||||||
|
</p>
|
||||||
|
<!-- 전문가 상담 및 예약 버튼 (상단 오른쪽) -->
|
||||||
|
|
||||||
|
<div class="main_action_row">
|
||||||
|
<a href="<?php echo G5_BBS_URL ?>/board.php?bo_table=order" class="btn_box white" >
|
||||||
|
<div class="btn_icon">🏢</div>
|
||||||
|
<div class="btn_txt">
|
||||||
|
<strong>창호 온라인 주문</strong>
|
||||||
|
<p>실시간 직접 견적 및 주문 확정</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<div class="btn_box white" onclick="openExpertVisitPopup(<?php echo $wr_id; ?>)">
|
||||||
|
<div class="btn_icon">👨🔧</div>
|
||||||
|
<div class="btn_txt">
|
||||||
|
<strong>창호 전문가 부르기</strong>
|
||||||
|
<p>방문 실측 및 맞춤 상담 신청</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="floating_as_badge">
|
|
||||||
<p>전국 대리점망</p>
|
|
||||||
<strong>A/S 10년 보장</strong>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</div>
|
||||||
|
<div class="floating_as_badge">
|
||||||
|
<p>전국 대리점망</p>
|
||||||
|
<strong>A/S 10년 보장</strong>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
@@ -321,6 +388,23 @@ include_once(G5_ADMIN_PATH . '/order_manage/components/_expert_visit_popups.php'
|
|||||||
if (typeof initProducts === 'function') {
|
if (typeof initProducts === 'function') {
|
||||||
initProducts(productsData);
|
initProducts(productsData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the house map container
|
||||||
|
const houseMapContainer = document.getElementById('house-map-container');
|
||||||
|
// Get all product items
|
||||||
|
const productItems = document.querySelectorAll('.product-item');
|
||||||
|
|
||||||
|
// Add click event listener to each product item
|
||||||
|
productItems.forEach(item => {
|
||||||
|
item.addEventListener('click', function() {
|
||||||
|
// Get the image URL from the data-img attribute
|
||||||
|
const imageUrl = this.getAttribute('data-img');
|
||||||
|
if (imageUrl) {
|
||||||
|
// Update the background image of the house map container
|
||||||
|
houseMapContainer.style.backgroundImage = `url('${imageUrl}')`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -377,4 +461,4 @@ include_once(G5_ADMIN_PATH . '/order_manage/components/_expert_visit_popups.php'
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
@@ -79,7 +79,7 @@ function initProducts(productsData) {
|
|||||||
preview.classList.add('fixed-mode');
|
preview.classList.add('fixed-mode');
|
||||||
preview.style.display = 'flex';
|
preview.style.display = 'flex';
|
||||||
};
|
};
|
||||||
hotspotLayer.appendChild(hs);
|
// hotspotLayer.appendChild(hs);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
function initProducts(productsData) {
|
|
||||||
const map = document.getElementById('main-map');
|
|
||||||
const hotspotLayer = document.getElementById('hotspot-layer');
|
|
||||||
const preview = document.getElementById('hover-preview');
|
|
||||||
const previewGrid = document.getElementById('preview-grid');
|
|
||||||
// const coordDisplay = document.getElementById('coord-display');
|
|
||||||
|
|
||||||
// 그룹화 로직
|
|
||||||
const groups = {};
|
|
||||||
productsData.forEach(p => {
|
|
||||||
const key = `${parseFloat(p.xPct).toFixed(1)}_${parseFloat(p.yPct).toFixed(1)}`;
|
|
||||||
if (!groups[key]) groups[key] = [];
|
|
||||||
groups[key].push(p);
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.keys(groups).forEach(key => {
|
|
||||||
const group = groups[key];
|
|
||||||
const hs = document.createElement('div');
|
|
||||||
hs.className = 'hotspot';
|
|
||||||
hs.style.left = group[0].xPct + '%';
|
|
||||||
hs.style.top = group[0].yPct + '%';
|
|
||||||
hs.style.transform = 'translate(-50%, -50%)';
|
|
||||||
|
|
||||||
hs.onmouseenter = () => {
|
|
||||||
preview.style.display = 'block';
|
|
||||||
previewGrid.innerHTML = group.map(p => `
|
|
||||||
<div class="product-item">
|
|
||||||
<div class="product-img-box"><img src="${p.img_url}" onerror="this.src='https://via.placeholder.com/200x120?text=No+Image'"></div>
|
|
||||||
<div class="text-[10px] text-blue-400 font-bold mb-1">${p.page}</div>
|
|
||||||
<h4 class="text-white text-[13px] font-bold truncate">${p.title}</h4>
|
|
||||||
<p class="text-slate-500 text-[10px] line-clamp-2">${p.desc}</p>
|
|
||||||
</div>
|
|
||||||
`).join('');
|
|
||||||
};
|
|
||||||
hs.onmouseleave = () => preview.style.display = 'none';
|
|
||||||
hs.onmousemove = (e) => {
|
|
||||||
let x = e.clientX + 30;
|
|
||||||
let y = e.clientY + 30;
|
|
||||||
if (x + 540 > window.innerWidth) x = e.clientX - 560;
|
|
||||||
if (y + preview.offsetHeight > window.innerHeight) y = window.innerHeight - preview.offsetHeight - 20;
|
|
||||||
preview.style.left = x + 'px';
|
|
||||||
preview.style.top = y + 'px';
|
|
||||||
};
|
|
||||||
hotspotLayer.appendChild(hs);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 좌표 도구
|
|
||||||
// map.onmousemove = (e) => {
|
|
||||||
// const r = map.getBoundingClientRect();
|
|
||||||
// coordDisplay.textContent = `X: ${((e.clientX-r.left)/r.width*100).toFixed(1)}%, Y: ${((e.clientY-r.top)/r.height*100).toFixed(1)}%`;
|
|
||||||
// };
|
|
||||||
// map.onclick = (e) => {
|
|
||||||
// const r = map.getBoundingClientRect();
|
|
||||||
// prompt("좌표:", `xPct: ${((e.clientX-r.left)/r.width*100).toFixed(1)}, yPct: ${((e.clientY-r.top)/r.height*100).toFixed(1)}`);
|
|
||||||
// };
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
function initProducts(productsData) {
|
|
||||||
const map = document.getElementById('main-map');
|
|
||||||
const hotspotLayer = document.getElementById('hotspot-layer');
|
|
||||||
const preview = document.getElementById('hover-preview');
|
|
||||||
const previewGrid = document.getElementById('preview-grid');
|
|
||||||
// const coordDisplay = document.getElementById('coord-display');
|
|
||||||
|
|
||||||
let isFixed = false; // 팝업 고정 상태 변수
|
|
||||||
|
|
||||||
const groups = {};
|
|
||||||
productsData.forEach(p => {
|
|
||||||
const key = `${parseFloat(p.x_pct || p.xPct).toFixed(1)}_${parseFloat(p.y_pct || p.yPct).toFixed(1)}`;
|
|
||||||
if (!groups[key]) groups[key] = [];
|
|
||||||
groups[key].push(p);
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.keys(groups).forEach(key => {
|
|
||||||
const group = groups[key];
|
|
||||||
const hs = document.createElement('div');
|
|
||||||
hs.className = 'hotspot';
|
|
||||||
hs.style.left = (group[0].x_pct || group[0].xPct) + '%';
|
|
||||||
hs.style.top = (group[0].y_pct || group[0].yPct) + '%';
|
|
||||||
hs.style.transform = 'translate(-50%, -50%)';
|
|
||||||
|
|
||||||
// 팝업 내용 생성 함수
|
|
||||||
const updateContent = () => {
|
|
||||||
const gridClass = group.length === 1 ? 'single-item' : 'multi-items';
|
|
||||||
previewGrid.className = `products-grid ${gridClass}`;
|
|
||||||
previewGrid.innerHTML = group.map(p => `
|
|
||||||
<div class="product-item">
|
|
||||||
<div class="product-img-box"><img src="${p.img_url}" onerror="this.src='https://via.placeholder.com/200x120?text=No+Image'"></div>
|
|
||||||
<div class="info-content">
|
|
||||||
<div class="text-[11px] text-blue-400 font-bold mb-1">${p.page}</div>
|
|
||||||
<h4 class="text-white text-[16px] font-bold mb-2">${p.title}</h4>
|
|
||||||
<p class="text-slate-400 text-[13px] leading-relaxed">${p.desc}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`).join('');
|
|
||||||
};
|
|
||||||
|
|
||||||
// 마우스 진입 (호버 시작)
|
|
||||||
hs.onmouseenter = (e) => {
|
|
||||||
if (isFixed) return;
|
|
||||||
updateContent();
|
|
||||||
preview.style.display = 'block';
|
|
||||||
};
|
|
||||||
|
|
||||||
// 마우스 이동 (팝업이 마우스를 따라다님)
|
|
||||||
hs.onmousemove = (e) => {
|
|
||||||
if (isFixed) return;
|
|
||||||
let x = e.clientX + 20;
|
|
||||||
let y = e.clientY - (preview.offsetHeight / 2);
|
|
||||||
if (x + 560 > window.innerWidth) x = e.clientX - 580;
|
|
||||||
if (y < 20) y = 20;
|
|
||||||
preview.style.left = x + 'px';
|
|
||||||
preview.style.top = y + 'px';
|
|
||||||
};
|
|
||||||
|
|
||||||
// 마우스 이탈 (호버 종료)
|
|
||||||
hs.onmouseleave = () => {
|
|
||||||
if (isFixed) return;
|
|
||||||
preview.style.display = 'none';
|
|
||||||
};
|
|
||||||
|
|
||||||
// 클릭 시 고정
|
|
||||||
hs.onclick = (e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
isFixed = true;
|
|
||||||
updateContent();
|
|
||||||
preview.style.display = 'block';
|
|
||||||
|
|
||||||
// 고정 시에는 화면 중앙 근처 적절한 위치에 배치
|
|
||||||
let x = e.clientX + 30;
|
|
||||||
let y = e.clientY - (preview.offsetHeight / 2);
|
|
||||||
if (x + 720 > window.innerWidth) x = e.clientX - 730;
|
|
||||||
if (y < 20) y = 20;
|
|
||||||
|
|
||||||
preview.style.left = x + 'px';
|
|
||||||
preview.style.top = y + 'px';
|
|
||||||
preview.classList.add('fixed-mode');
|
|
||||||
};
|
|
||||||
|
|
||||||
hotspotLayer.appendChild(hs);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 외부 클릭 시 고정 해제 및 닫기
|
|
||||||
document.addEventListener('click', (e) => {
|
|
||||||
if (!preview.contains(e.target)) {
|
|
||||||
isFixed = false;
|
|
||||||
preview.style.display = 'none';
|
|
||||||
preview.classList.remove('fixed-mode');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// // 좌표 도구
|
|
||||||
// map.onmousemove = (e) => {
|
|
||||||
// const r = map.getBoundingClientRect();
|
|
||||||
// coordDisplay.textContent = `X: ${((e.clientX-r.left)/r.width*100).toFixed(1)}%, Y: ${((e.clientY-r.top)/r.height*100).toFixed(1)}%`;
|
|
||||||
// };
|
|
||||||
// map.onclick = (e) => {
|
|
||||||
// const r = map.getBoundingClientRect();
|
|
||||||
// prompt("좌표:", `xPct: ${((e.clientX-r.left)/r.width*100).toFixed(1)}, yPct: ${((e.clientY-r.top)/r.height*100).toFixed(1)}`);
|
|
||||||
// };
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,24 @@
|
|||||||
/**
|
/**
|
||||||
* [최종 통합본] 제품 사이드 메뉴 및 메인 맵 연동 모듈 (products2.js)
|
* [최종 통합본] 제품 사이드 메뉴 및 메인 맵 연동 모듈 (products2.js)
|
||||||
* 1: 중앙팝업, 2: 점선연결, 3: 제자리확대, 4: 1초 지연 후 중앙팝업
|
* 1: 중앙팝업, 2: 점선연결, 3: 제자리확대, 4: 1초 지연 후 중앙팝업, 5: 팝업 박스 표시, 6: 점선연결 + 팝업 박스 표시
|
||||||
* 5: 점선연결 + 1초후 중앙팝업
|
|
||||||
*/
|
*/
|
||||||
(function() {
|
(function() {
|
||||||
// 💡 설정: 원하는 모드 번호를 입력하세요.
|
// 💡 설정: 원하는 모드 번호를 입력하세요.
|
||||||
const POPUP_MODE = 5;
|
const POPUP_MODE = 6; // 6번 모드로 설정합니다.
|
||||||
|
// 💡 설정: 팝업 박스에 표시할 내용의 타입을 선택하세요 ('text' 또는 'image').
|
||||||
|
const POPUP_CONTENT_DISPLAY_TYPE = 'image'; // 'text' 또는 'image'로 변경하여 테스트
|
||||||
|
|
||||||
let popupTimer = null; // 4번 모드용 타이머
|
let popupTimer = null; // 4번 모드용 타이머
|
||||||
|
let hoverTimeout = null; // 호버 인텐트 지연 타이머
|
||||||
|
const HOVER_DELAY = 50; // 마우스가 완전히 벗어났다고 판단할 지연 시간 (밀리초)
|
||||||
|
const MAX_MOVE_DISTANCE = 10; // 팝업이 핫스팟에서 이동할 수 있는 최대 거리 (px)
|
||||||
|
|
||||||
|
|
||||||
|
// 모든 효과와 타이머를 제거하는 청소기 함수 (popupBox 숨기는 로직은 제외)
|
||||||
|
function clearAllPopupsContent() { // 함수 이름 변경: 내용만 초기화
|
||||||
|
console.log('clearAllPopupsContent called!');
|
||||||
|
// console.trace(); // 이제 제거해도 됩니다.
|
||||||
|
|
||||||
// 모든 효과와 타이머를 제거하는 청소기 함수
|
|
||||||
function clearAllPopups() {
|
|
||||||
// 실행 중인 타이머가 있으면 취소
|
// 실행 중인 타이머가 있으면 취소
|
||||||
if (popupTimer) {
|
if (popupTimer) {
|
||||||
clearTimeout(popupTimer);
|
clearTimeout(popupTimer);
|
||||||
@@ -35,12 +43,24 @@
|
|||||||
img.style.transform = '';
|
img.style.transform = '';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// popupContent 내용 및 스타일 초기화 (popupBox 자체는 건드리지 않음)
|
||||||
|
const popupBox = document.getElementById('popup-box');
|
||||||
|
if (popupBox) {
|
||||||
|
const popupContent = popupBox.querySelector('.content');
|
||||||
|
if (popupContent) {
|
||||||
|
popupContent.innerHTML = ''; // 내용 비우기
|
||||||
|
popupContent.style.cssText = ''; // 모든 인라인 스타일 초기화
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function initProductEvents() {
|
function initProductEvents() {
|
||||||
const productItems = document.querySelectorAll('.product-section .product-item');
|
const productItems = document.querySelectorAll('.product-section .product-item');
|
||||||
const mainArea = document.querySelector('.product-main');
|
const mainArea = document.querySelector('.product-main');
|
||||||
const section = document.querySelector('.product-section');
|
const section = document.querySelector('.product-section');
|
||||||
|
const popupBox = document.getElementById('popup-box');
|
||||||
|
const popupContent = popupBox ? popupBox.querySelector('.content') : null;
|
||||||
|
|
||||||
if (!productItems.length || !mainArea) return;
|
if (!productItems.length || !mainArea) return;
|
||||||
|
|
||||||
@@ -48,24 +68,262 @@
|
|||||||
const imgElement = item.querySelector('.product-img img');
|
const imgElement = item.querySelector('.product-img img');
|
||||||
const imgSrc = item.dataset.img || (imgElement ? imgElement.src : '');
|
const imgSrc = item.dataset.img || (imgElement ? imgElement.src : '');
|
||||||
const proLink = item.dataset.prolink;
|
const proLink = item.dataset.prolink;
|
||||||
|
const x1 = parseFloat(item.dataset.x1);
|
||||||
|
const y1 = parseFloat(item.dataset.y1);
|
||||||
|
|
||||||
|
// Get product details from data attributes
|
||||||
|
const title = item.dataset.title;
|
||||||
|
const desc = item.dataset.desc;
|
||||||
|
const content = item.dataset.content;
|
||||||
|
|
||||||
|
|
||||||
item.addEventListener('mouseenter', function() {
|
item.addEventListener('mouseenter', function() {
|
||||||
clearAllPopups(); // 새로 시작하기 전 초기화
|
console.log('Mouse entered product-item:', title);
|
||||||
|
|
||||||
const x1 = this.dataset.x1;
|
// 섹션 숨김 지연 타이머가 있다면 취소 (호버 깜빡임 방지)
|
||||||
const y1 = this.dataset.y1;
|
if (hoverTimeout) {
|
||||||
|
console.log('Clearing hoverTimeout on mouseenter.');
|
||||||
|
clearTimeout(hoverTimeout);
|
||||||
|
hoverTimeout = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (x1 && y1) {
|
// 새로운 팝업을 띄우기 전에 이전 팝업의 내용만 초기화
|
||||||
// 1. 핫스팟(블루 스폿)은 어떤 모드든 즉시 표시
|
clearAllPopupsContent();
|
||||||
const hotspot = document.querySelector('.product-hotspot');
|
|
||||||
if (hotspot) {
|
// 팝업 박스를 명시적으로 보이는 상태로 설정 (애니메이션 시작 전)
|
||||||
hotspot.style.left = x1 + '%';
|
if (popupBox) {
|
||||||
hotspot.style.top = y1 + '%';
|
gsap.killTweensOf(popupBox); // 혹시 모를 숨김 애니메이션 중단
|
||||||
hotspot.style.display = 'block';
|
popupBox.style.display = 'block';
|
||||||
|
|
||||||
|
// 애니메이션 초기 상태 설정
|
||||||
|
popupBox.style.width = '0px';
|
||||||
|
popupBox.style.height = '0px';
|
||||||
|
popupBox.style.opacity = '0';
|
||||||
|
popupBox.style.transform = 'none'; // transform 제거
|
||||||
|
|
||||||
|
// mainRect는 popupBox를 포함하는 product-main의 크기 정보
|
||||||
|
|
||||||
|
|
||||||
|
// 핫스팟 위치에 따라 팝업의 초기 시작 지점 설정
|
||||||
|
const isLeft = this.closest('.product-side').classList.contains('left');
|
||||||
|
const rect = item.getBoundingClientRect();//this.getBoundingClientRect();
|
||||||
|
const mainRect = mainArea.getBoundingClientRect();
|
||||||
|
const startX = isLeft ? rect.right : rect.left;
|
||||||
|
const startY = rect.bottom + (rect.height / 2); //rect.bottom + (rect.height / 2);
|
||||||
|
|
||||||
|
|
||||||
|
if (isLeft) {
|
||||||
|
// 핫스팟이 왼쪽에 있으면 팝업은 mainArea의 좌측 상단에서 시작
|
||||||
|
popupBox.style.left = startX+'px';
|
||||||
|
popupBox.style.top = startY+'px';
|
||||||
|
} else {
|
||||||
|
// 핫스팟이 오른쪽에 있으면 팝업은 mainArea의 우측 상단에서 시작
|
||||||
|
popupBox.style.left = startX +'px';
|
||||||
|
popupBox.style.top = startY +'px';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isNaN(x1) && !isNaN(y1)) {
|
||||||
|
// 1. 핫스팟(블루 스폿)은 어떤 모드든 즉시 표시
|
||||||
|
if(x1 && y1) {
|
||||||
|
const hotspot = document.querySelector('.product-hotspot');
|
||||||
|
if (hotspot) {
|
||||||
|
hotspot.style.left = x1 + '%';
|
||||||
|
hotspot.style.top = y1 + '%';
|
||||||
|
hotspot.style.display = 'block';
|
||||||
|
}
|
||||||
|
}
|
||||||
// 2. 모드별 효과 실행
|
// 2. 모드별 효과 실행
|
||||||
if (POPUP_MODE === 4) {
|
if (POPUP_MODE === 5 || POPUP_MODE === 6) {
|
||||||
|
if (popupBox && popupContent) {
|
||||||
|
// Set popup dimensions
|
||||||
|
const popupWidth = 600; // 요청하신 대로 600
|
||||||
|
const popupHeight = 500; // 요청하신 대로 500
|
||||||
|
const POPUP_HORIZONTAL_OFFSET = 20; // 핫스팟과 팝업 사이의 가로 간격 (px)
|
||||||
|
|
||||||
|
// popupContent의 기본 스타일 설정 (매우 중요!)
|
||||||
|
popupContent.style.width = '100%';
|
||||||
|
popupContent.style.height = '100%';
|
||||||
|
popupContent.style.display = 'flex';
|
||||||
|
popupContent.style.alignItems = 'center';
|
||||||
|
popupContent.style.justifyContent = 'center';
|
||||||
|
popupContent.style.color = '#fff'; // 기본 텍스트 색상
|
||||||
|
popupContent.style.overflow = 'hidden'; // 이 줄을 추가합니다.
|
||||||
|
popupContent.style.padding = '0'; // 이 줄을 추가합니다.
|
||||||
|
|
||||||
|
// Populate popup content based on POPUP_CONTENT_DISPLAY_TYPE
|
||||||
|
if (POPUP_CONTENT_DISPLAY_TYPE === 'image' && imgElement) {
|
||||||
|
popupContent.innerHTML = ''; // Clear previous content
|
||||||
|
popupContent.style.background = 'none'; // 이미지 표시 시 배경 제거
|
||||||
|
|
||||||
|
const clone = imgElement.cloneNode(true);
|
||||||
|
clone.src = imgSrc;
|
||||||
|
// clone.id = 'active-popup-img'; // 이 줄을 제거합니다!
|
||||||
|
clone.style.width = '100%'; // Make image fit popup box
|
||||||
|
clone.style.height = '100%';
|
||||||
|
clone.style.objectFit = 'contain'; // 'cover'에서 'contain'으로 변경
|
||||||
|
// clone.style.cursor = proLink ? 'pointer' : 'default'; // 이 줄을 주석 처리하거나 제거합니다.
|
||||||
|
clone.style.pointerEvents = 'none'; // 이미지 위에서 마우스 이벤트 방지
|
||||||
|
if (proLink) {
|
||||||
|
clone.onclick = () => { location.href = proLink; };
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log('--- Debugging appendChild ---');
|
||||||
|
// console.log('proLink:', proLink);
|
||||||
|
// console.log('Clone element:', clone);
|
||||||
|
// console.log('popupContent BEFORE append:', popupContent.innerHTML);
|
||||||
|
// console.log('popupContent.style.cssText BEFORE append:', popupContent.style.cssText); // 스타일 확인
|
||||||
|
popupContent.appendChild(clone);
|
||||||
|
// console.log('popupContent AFTER append:', popupContent.innerHTML);
|
||||||
|
// console.log('popupContent.style.cssText AFTER append:', popupContent.style.cssText); // 스타일 확인
|
||||||
|
// console.log('popupContent children AFTER append:', popupContent.children.length);
|
||||||
|
// console.log('popupContent ', popupContent);
|
||||||
|
// console.log('popupBox ', popupBox);
|
||||||
|
// console.log('--- End Debugging ---');
|
||||||
|
|
||||||
|
} else { // Default to text content or if POPUP_CONTENT_DISPLAY_TYPE is 'text'
|
||||||
|
popupContent.innerHTML = `
|
||||||
|
<h3>${title}</h3>
|
||||||
|
<p>${desc}</p>
|
||||||
|
<p>${content}</p>
|
||||||
|
${proLink ? `<a href="${proLink}" style="color: white; text-decoration: underline;">자세히 보기</a>` : ''}
|
||||||
|
`;
|
||||||
|
// 텍스트 표시 시 배경 적용
|
||||||
|
popupContent.style.background = 'linear-gradient(135deg, #667eea, #764ba2)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const isLeft = this.closest('.product-side').classList.contains('left');
|
||||||
|
const rect = item.getBoundingClientRect();
|
||||||
|
const mainRect = mainArea.getBoundingClientRect();
|
||||||
|
const startX = isLeft ? rect.right : rect.left;
|
||||||
|
const startY = rect.bottom + (rect.height / 2);
|
||||||
|
// const hotspotX_px = startX +popupWidth;
|
||||||
|
// const hotspotY_px = !isLeft ? startY+popupHeight : startY - popupHeight;
|
||||||
|
|
||||||
|
const corners = {
|
||||||
|
topLeft: {
|
||||||
|
x: rect.left ,
|
||||||
|
y: rect.top
|
||||||
|
},
|
||||||
|
topRight: {
|
||||||
|
x: rect.right ,
|
||||||
|
y: rect.top
|
||||||
|
},
|
||||||
|
bottomLeft: {
|
||||||
|
x: rect.left ,
|
||||||
|
y: rect.bottom
|
||||||
|
},
|
||||||
|
bottomRight: {
|
||||||
|
x: rect.right ,
|
||||||
|
y: rect.bottom
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// const hotspotX_px = isLeft ? rect.right : rect.left - popupWidth -POPUP_HORIZONTAL_OFFSET ;
|
||||||
|
// const hotspotY_px = isLeft ? rect.top - rect.height :rect.y;
|
||||||
|
const hotspotX_px = isLeft ? 462.0833435058594 : 922.0833740234375 ;
|
||||||
|
const hotspotY_px = isLeft ? 174.66668701171875 :247.33334350585938;
|
||||||
|
console.log(isLeft);
|
||||||
|
console.log(mainRect);
|
||||||
|
console.log(rect);
|
||||||
|
console.log(hotspotX_px);
|
||||||
|
console.log(hotspotY_px);
|
||||||
|
// Determine if hotspot is on the left or right half of the mainArea
|
||||||
|
const isHotspotLeftHalf = x1 < 50;
|
||||||
|
|
||||||
|
// Calculate ideal raw targetLeft based on side
|
||||||
|
let idealTargetLeft_px;
|
||||||
|
if (isHotspotLeftHalf) {
|
||||||
|
// Hotspot on left, popup appears to its right
|
||||||
|
idealTargetLeft_px = hotspotX_px + POPUP_HORIZONTAL_OFFSET;
|
||||||
|
} else {
|
||||||
|
// Hotspot on right, popup appears to its left
|
||||||
|
idealTargetLeft_px = hotspotX_px - popupWidth - POPUP_HORIZONTAL_OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate ideal raw targetTop (vertically centered with hotspot)
|
||||||
|
let idealTargetTop_px = hotspotY_px - (popupHeight / 2);
|
||||||
|
|
||||||
|
// Clamp ideal targetLeft and targetTop to stay within mainArea bounds
|
||||||
|
let clampedIdealTargetLeft_px = Math.max(0, Math.min(idealTargetLeft_px, mainRect.width - popupWidth));
|
||||||
|
let clampedIdealTargetTop_px = Math.max(0, Math.min(idealTargetTop_px, mainRect.height - popupHeight));
|
||||||
|
|
||||||
|
// Calculate actual final position, limiting movement distance
|
||||||
|
let finalTargetLeft_px = clampedIdealTargetLeft_px;
|
||||||
|
let finalTargetTop_px = clampedIdealTargetTop_px;
|
||||||
|
|
||||||
|
// Calculate distance from hotspot center to clamped ideal popup center
|
||||||
|
const hotspotCenterToPopupCenterX = clampedIdealTargetLeft_px + (popupWidth / 2) - hotspotX_px;
|
||||||
|
const hotspotCenterToPopupCenterY = clampedIdealTargetTop_px + (popupHeight / 2) - hotspotY_px;
|
||||||
|
const distance = Math.sqrt(
|
||||||
|
hotspotCenterToPopupCenterX * hotspotCenterToPopupCenterX +
|
||||||
|
hotspotCenterToPopupCenterY * hotspotCenterToPopupCenterY
|
||||||
|
);
|
||||||
|
|
||||||
|
if (distance > MAX_MOVE_DISTANCE) {
|
||||||
|
// If distance exceeds max, scale down the movement vector
|
||||||
|
const ratio = MAX_MOVE_DISTANCE / distance;
|
||||||
|
finalTargetLeft_px = hotspotX_px + (hotspotCenterToPopupCenterX * ratio) - (popupWidth / 2);
|
||||||
|
finalTargetTop_px = hotspotY_px + (hotspotCenterToPopupCenterY * ratio) - (popupHeight / 2);
|
||||||
|
|
||||||
|
// Re-clamp to ensure it stays within mainArea bounds after adjustment
|
||||||
|
finalTargetLeft_px = Math.max(0, Math.min(finalTargetLeft_px, mainRect.width - popupWidth));
|
||||||
|
finalTargetTop_px = Math.max(0, Math.min(finalTargetTop_px, mainRect.height - popupHeight));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 팝업 박스를 보여주는 애니메이션 (크기, 위치, 투명도 동시 애니메이션)
|
||||||
|
gsap.to(popupBox, {
|
||||||
|
width: popupWidth, // 최종 너비
|
||||||
|
height: popupHeight, // 최종 높이
|
||||||
|
left: hotspotX_px,//finalTargetLeft_px, // 최종 왼쪽 위치
|
||||||
|
top: hotspotY_px,//finalTargetTop_px, // 최종 위쪽 위치
|
||||||
|
opacity: 1, // 최종 투명도
|
||||||
|
transform: 'none', // transform 속성 제거
|
||||||
|
duration: 1.5, // 요청하신 대로 1.5초로 변경
|
||||||
|
ease: "power2.out",
|
||||||
|
pointerEvents: 'auto',
|
||||||
|
onComplete: () => { // 이 onComplete 콜백을 추가합니다.
|
||||||
|
popupBox.style.opacity = '1'; // 애니메이션 완료 후 opacity를 1로 강제
|
||||||
|
popupBox.style.display = 'block'; // 애니메이션 완료 후 display를 block으로 강제
|
||||||
|
popupBox.style.transform = 'none'; // transform 속성 초기화 (중요)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Mode 6 specific: Add connector line
|
||||||
|
if (POPUP_MODE === 6 &&x1 &&y1) {
|
||||||
|
const rect = this.getBoundingClientRect();
|
||||||
|
const mainRect = mainArea.getBoundingClientRect();
|
||||||
|
const targetX = mainRect.left + (mainRect.width * (x1 / 100));
|
||||||
|
const targetY = mainRect.top + (mainRect.height * (y1 / 100));
|
||||||
|
const isLeft = this.closest('.product-side').classList.contains('left');
|
||||||
|
const startX = isLeft ? rect.right : rect.left;
|
||||||
|
const startY = rect.top + (rect.height / 2);
|
||||||
|
const dx = targetX - startX;
|
||||||
|
const dy = targetY - startY;
|
||||||
|
const dist = Math.sqrt(dx * dx + dy * dy);
|
||||||
|
let angle = Math.atan2(dy, dx) * 180 / Math.PI;
|
||||||
|
if (!isLeft) angle += 180;
|
||||||
|
|
||||||
|
this.style.setProperty('--line-width', dist + 'px');
|
||||||
|
this.style.setProperty('--line-angle', angle + 'deg');
|
||||||
|
this.classList.add('show-connector');
|
||||||
|
requestAnimationFrame(() => this.classList.add('active'));
|
||||||
|
// Note: imgElement.style.transform = 'scale(1.2)' is not applied here
|
||||||
|
// as the image is either in the popup or not the primary focus for mode 6.
|
||||||
|
// If you want the side image to scale, uncomment the following:
|
||||||
|
// if (imgElement) imgElement.style.transform = 'scale(1.2)';
|
||||||
|
|
||||||
|
if (imgElement && proLink) {
|
||||||
|
// This click handler is for the side image, not the popup image
|
||||||
|
// imgElement.style.cursor = 'pointer'; // 이 줄을 주석 처리하거나 제거합니다.
|
||||||
|
imgElement.onclick = () => { location.href = proLink; };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (POPUP_MODE === 4) {
|
||||||
// [모드 4] 1초 지연 후 중앙 팝업
|
// [모드 4] 1초 지연 후 중앙 팝업
|
||||||
popupTimer = setTimeout(() => {
|
popupTimer = setTimeout(() => {
|
||||||
if (imgElement) {
|
if (imgElement) {
|
||||||
@@ -99,8 +357,8 @@
|
|||||||
// [모드 2] 점선 연결선 정밀 계산
|
// [모드 2] 점선 연결선 정밀 계산
|
||||||
const rect = this.getBoundingClientRect();
|
const rect = this.getBoundingClientRect();
|
||||||
const mainRect = mainArea.getBoundingClientRect();
|
const mainRect = mainArea.getBoundingClientRect();
|
||||||
const targetX = mainRect.left + (mainRect.width * (parseFloat(x1) / 100));
|
const targetX = mainRect.left + (mainRect.width * (x1 / 100));
|
||||||
const targetY = mainRect.top + (mainRect.height * (parseFloat(y1) / 100));
|
const targetY = mainRect.top + (mainRect.height * (y1 / 100));
|
||||||
const isLeft = this.closest('.product-side').classList.contains('left');
|
const isLeft = this.closest('.product-side').classList.contains('left');
|
||||||
const startX = isLeft ? rect.right : rect.left;
|
const startX = isLeft ? rect.right : rect.left;
|
||||||
const startY = rect.top + (rect.height / 2);
|
const startY = rect.top + (rect.height / 2);
|
||||||
@@ -120,57 +378,15 @@
|
|||||||
imgElement.style.cursor = 'pointer';
|
imgElement.style.cursor = 'pointer';
|
||||||
imgElement.onclick = () => { location.href = proLink; };
|
imgElement.onclick = () => { location.href = proLink; };
|
||||||
}
|
}
|
||||||
|
} else if (POPUP_MODE === 3 && imgElement) { // 3번 모드 로직 추가
|
||||||
} else if (POPUP_MODE === 3 && imgElement) {
|
|
||||||
// [모드 3] 제자리 600 확대
|
// [모드 3] 제자리 600 확대
|
||||||
imgElement.src = imgSrc;
|
// imgElement.src = imgSrc;
|
||||||
imgElement.classList.add('mode-self-zoom');
|
imgElement.classList.add('mode-self-zoom');
|
||||||
if (proLink) {
|
if (proLink) {
|
||||||
imgElement.style.cursor = 'pointer';
|
imgElement.style.cursor = 'pointer';
|
||||||
imgElement.style.pointerEvents = 'auto';
|
imgElement.style.pointerEvents = 'auto';
|
||||||
imgElement.onclick = () => { location.href = proLink; };
|
imgElement.onclick = () => { location.href = proLink; };
|
||||||
}
|
}
|
||||||
} else if(POPUP_MODE === 5 && imgElement) {
|
|
||||||
// [모드 2] 점선 연결선 정밀 계산
|
|
||||||
const rect = this.getBoundingClientRect();
|
|
||||||
const mainRect = mainArea.getBoundingClientRect();
|
|
||||||
const targetX = mainRect.left + (mainRect.width * (parseFloat(x1) / 100));
|
|
||||||
const targetY = mainRect.top + (mainRect.height * (parseFloat(y1) / 100));
|
|
||||||
const isLeft = this.closest('.product-side').classList.contains('left');
|
|
||||||
const startX = isLeft ? rect.right : rect.left;
|
|
||||||
const startY = rect.top + (rect.height / 2);
|
|
||||||
const dx = targetX - startX;
|
|
||||||
const dy = targetY - startY;
|
|
||||||
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
||||||
let angle = Math.atan2(dy, dx) * 180 / Math.PI;
|
|
||||||
if (!isLeft) angle += 180;
|
|
||||||
|
|
||||||
this.style.setProperty('--line-width', dist + 'px');
|
|
||||||
this.style.setProperty('--line-angle', angle + 'deg');
|
|
||||||
this.classList.add('show-connector');
|
|
||||||
requestAnimationFrame(() => this.classList.add('active'));
|
|
||||||
if (imgElement) imgElement.style.transform = 'scale(1.2)';
|
|
||||||
|
|
||||||
if (imgElement && proLink) {
|
|
||||||
imgElement.style.cursor = 'pointer';
|
|
||||||
imgElement.onclick = () => { location.href = proLink; };
|
|
||||||
}
|
|
||||||
|
|
||||||
var popupTimer = setTimeout(() => {
|
|
||||||
if (imgElement) {
|
|
||||||
const clone = imgElement.cloneNode(true);
|
|
||||||
clone.id = 'active-popup-img';
|
|
||||||
clone.src = imgSrc;
|
|
||||||
if (proLink) {
|
|
||||||
clone.style.cursor = 'pointer';
|
|
||||||
clone.style.pointerEvents = 'auto';
|
|
||||||
clone.onclick = () => { location.href = proLink; };
|
|
||||||
}
|
|
||||||
mainArea.appendChild(clone);
|
|
||||||
requestAnimationFrame(() => clone.classList.add('active'));
|
|
||||||
}
|
|
||||||
}, 1000); // 1000ms = 1초 대기
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -186,12 +402,58 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 마우스가 아이템을 벗어나면 즉시 청소 (타이머 취소 포함)
|
// 마우스가 아이템을 벗어나면 즉시 청소 (타이머 취소 포함)
|
||||||
item.addEventListener('mouseleave', clearAllPopups);
|
item.addEventListener('mouseleave', function() {
|
||||||
|
console.log('Mouse left item!');
|
||||||
|
console.log('Setting hoverTimeout to hide popup in', HOVER_DELAY, 'ms');
|
||||||
|
|
||||||
|
// 팝업 숨김을 HOVER_DELAY만큼 지연시킵니다.
|
||||||
|
hoverTimeout = setTimeout(() => {
|
||||||
|
console.log('hoverTimeout triggered: Hiding popup.');
|
||||||
|
clearAllPopupsContent(); // 내용만 초기화
|
||||||
|
const popupBox = document.getElementById('popup-box');
|
||||||
|
if (popupBox) {
|
||||||
|
gsap.killTweensOf(popupBox); // 현재 진행 중인 애니메이션을 즉시 중단
|
||||||
|
gsap.to(popupBox, {
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
opacity: 0,
|
||||||
|
duration: 0.4,
|
||||||
|
onComplete: () => {
|
||||||
|
popupBox.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, HOVER_DELAY); // HOVER_DELAY만큼 지연
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 섹션 전체를 벗어나도 청소 (안전장치)
|
// 섹션 전체를 벗어나면 팝업 박스 숨기기
|
||||||
if (section) {
|
if (section) {
|
||||||
section.addEventListener('mouseleave', clearAllPopups);
|
section.addEventListener('mouseleave', function() {
|
||||||
|
console.log('Mouse left product-section!');
|
||||||
|
console.log('Setting hoverTimeout to hide popup in', HOVER_DELAY, 'ms');
|
||||||
|
|
||||||
|
// 팝업 숨김을 HOVER_DELAY만큼 지연시킵니다.
|
||||||
|
hoverTimeout = setTimeout(() => {
|
||||||
|
console.log('hoverTimeout triggered: Hiding popup.');
|
||||||
|
clearAllPopupsContent(); // 내용만 초기화
|
||||||
|
const popupBox = document.getElementById('popup-box');
|
||||||
|
if (popupBox) {
|
||||||
|
gsap.killTweensOf(popupBox); // 현재 진행 중인 애니메이션을 즉시 중단
|
||||||
|
gsap.to(popupBox, {
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
opacity: 0,
|
||||||
|
duration: 0.4,
|
||||||
|
onComplete: () => {
|
||||||
|
popupBox.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, HOVER_DELAY); // HOVER_DELAY만큼 지연
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,4 +463,5 @@
|
|||||||
} else {
|
} else {
|
||||||
initProductEvents();
|
initProductEvents();
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
function initProductEvents() {
|
|
||||||
// 💡 설정: 1(메인중앙), 2(점선), 3(제자리확대)
|
|
||||||
const POPUP_MODE = 1;
|
|
||||||
|
|
||||||
const productItems = document.querySelectorAll('.product-section .product-item');
|
|
||||||
const mainArea = document.querySelector('.product-main');
|
|
||||||
|
|
||||||
if (!productItems.length) return;
|
|
||||||
|
|
||||||
productItems.forEach(item => {
|
|
||||||
// 💡 [수정] 데이터 속성에서 이미지 경로 직접 읽기 (없으면 내부 img 사용)
|
|
||||||
const imgSrc = item.dataset.img || item.querySelector('.product-img img').src;
|
|
||||||
const imgElement = item.querySelector('.product-img img');
|
|
||||||
|
|
||||||
item.addEventListener('mouseenter', function() {
|
|
||||||
clearAllPopups();
|
|
||||||
const x1 = this.dataset.x1;
|
|
||||||
const y1 = this.dataset.y1;
|
|
||||||
|
|
||||||
if (x1 && y1) {
|
|
||||||
ProductModule.setHotspot(x1, y1);
|
|
||||||
|
|
||||||
if (POPUP_MODE === 1 && mainArea) {
|
|
||||||
// [모드 1] 메인 중앙 복제 팝업
|
|
||||||
const clone = document.createElement('img');
|
|
||||||
clone.src = imgSrc; // 💡 전달받은 경로로 로드
|
|
||||||
clone.id = 'active-popup-img';
|
|
||||||
mainArea.appendChild(clone);
|
|
||||||
requestAnimationFrame(() => clone.classList.add('active'));
|
|
||||||
|
|
||||||
} else if (POPUP_MODE === 2) {
|
|
||||||
// [모드 2] 점선 연결 (기존 로직 동일)
|
|
||||||
const rect = this.getBoundingClientRect();
|
|
||||||
const mainRect = mainArea.getBoundingClientRect();
|
|
||||||
const targetX = mainRect.left + (mainRect.width * (parseFloat(x1) / 100));
|
|
||||||
const targetY = mainRect.top + (mainRect.height * (parseFloat(y1) / 100));
|
|
||||||
const isLeft = this.closest('.product-side').classList.contains('left');
|
|
||||||
const startX = isLeft ? rect.right : rect.left;
|
|
||||||
const dx = targetX - startX;
|
|
||||||
const dy = targetY - (rect.top + rect.height/2);
|
|
||||||
let angle = Math.atan2(dy, dx) * 180 / Math.PI;
|
|
||||||
if (!isLeft) angle += 180;
|
|
||||||
|
|
||||||
this.style.setProperty('--line-width', Math.sqrt(dx*dx + dy*dy) + 'px');
|
|
||||||
this.style.setProperty('--line-angle', angle + 'deg');
|
|
||||||
this.classList.add('show-connector');
|
|
||||||
requestAnimationFrame(() => this.classList.add('active'));
|
|
||||||
|
|
||||||
} else if (POPUP_MODE === 3) {
|
|
||||||
// 💡 [모드 3] 제자리 400x400 확대
|
|
||||||
if (imgElement) {
|
|
||||||
imgElement.src = imgSrc; // 💡 이미지 경로 갱신
|
|
||||||
imgElement.classList.add('mode-self-zoom');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
item.addEventListener('mouseleave', function() {
|
|
||||||
clearAllPopups();
|
|
||||||
if (imgElement) imgElement.classList.remove('mode-self-zoom');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
function initProducts(productsData) {
|
|
||||||
const map = document.getElementById('main-map');
|
|
||||||
const hotspotLayer = document.getElementById('hotspot-layer');
|
|
||||||
const preview = document.getElementById('hover-preview');
|
|
||||||
const previewGrid = document.getElementById('preview-grid');
|
|
||||||
|
|
||||||
let isFixed = false;
|
|
||||||
const noImg = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAwIiBoZWlnaHQ9IjMwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjMjIyIi8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZpbGw9IiM0NDQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGR5PSIuM2VtIiBmb250LWZhbWl5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjI0Ij5ObyBJbWFnZTwvdGV4dD48L3N2Zz4=";
|
|
||||||
|
|
||||||
// 1. 그룹화 로직
|
|
||||||
const groups = {};
|
|
||||||
productsData.forEach(p => {
|
|
||||||
const key = `${parseFloat(p.xPct).toFixed(1)}_${parseFloat(p.yPct).toFixed(1)}`;
|
|
||||||
if (!groups[key]) groups[key] = [];
|
|
||||||
groups[key].push(p);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 2. 핫스팟 생성 및 이벤트
|
|
||||||
Object.keys(groups).forEach(key => {
|
|
||||||
const group = groups[key];
|
|
||||||
const hs = document.createElement('div');
|
|
||||||
hs.className = 'hotspot';
|
|
||||||
hs.style.left = group[0].xPct + '%';
|
|
||||||
hs.style.top = group[0].yPct + '%';
|
|
||||||
hs.style.transform = 'translate(-50%, -50%)';
|
|
||||||
|
|
||||||
const updateContent = (showFullContent) => {
|
|
||||||
const hasContent = group.some(p => p.content && p.content.trim() !== "");
|
|
||||||
const isSingle = group.length === 1;
|
|
||||||
|
|
||||||
if (showFullContent && hasContent) {
|
|
||||||
// 클릭 시: 상세 HTML 모드
|
|
||||||
previewGrid.className = `products-grid full-html-mode ${isSingle ? 'single-item' : 'multi-items'}`;
|
|
||||||
previewGrid.innerHTML = group.map(p => {
|
|
||||||
if (p.content && p.content.trim() !== "") {
|
|
||||||
return `<div class="editor-content-view">${p.content}</div>`;
|
|
||||||
} else {
|
|
||||||
const linkAttr = (p.link) ? `onclick="location.href='${p.link}'" style="cursor:pointer;"` : "";
|
|
||||||
return `<div class="product-item" ${linkAttr}>
|
|
||||||
<div class="product-img-box"><img src="${p.img_url}" onerror="this.onerror=null; this.src='${noImg}';"></div>
|
|
||||||
<div class="info-content">
|
|
||||||
<div class="text-[12px] text-blue-400 font-bold mb-2">${p.page}</div>
|
|
||||||
<h4 class="text-white text-[18px] font-bold mb-3">${p.title}</h4>
|
|
||||||
<p class="text-slate-400 text-[14px] leading-relaxed">${p.desc}</p>
|
|
||||||
${p.link ? '<div class="text-[11px] text-blue-500 mt-2">자세히 보기 ></div>' : ''}
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
}
|
|
||||||
}).join('<hr class="content-divider">');
|
|
||||||
} else {
|
|
||||||
// 호버 시: 요약 모드
|
|
||||||
const gridClass = isSingle ? 'single-item' : 'multi-items';
|
|
||||||
previewGrid.className = `products-grid ${gridClass}`;
|
|
||||||
previewGrid.innerHTML = group.map(p => {
|
|
||||||
const linkAttr = (p.link) ? `onclick="location.href='${p.link}'" style="cursor:pointer;"` : "";
|
|
||||||
return `<div class="product-item" ${linkAttr}>
|
|
||||||
<div class="product-img-box"><img src="${p.img_url}" onerror="this.onerror=null; this.src='${noImg}';"></div>
|
|
||||||
<div class="info-content">
|
|
||||||
<div class="text-[12px] text-blue-400 font-bold mb-2">${p.page}</div>
|
|
||||||
<h4 class="text-white text-[18px] font-bold mb-3">${p.title}</h4>
|
|
||||||
<p class="text-slate-400 text-[14px] leading-relaxed">${p.desc}</p>
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
}).join('');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
hs.onmouseenter = () => {
|
|
||||||
if (isFixed) return;
|
|
||||||
updateContent(false);
|
|
||||||
preview.style.display = 'block';
|
|
||||||
preview.classList.remove('fixed-mode');
|
|
||||||
};
|
|
||||||
|
|
||||||
hs.onmouseleave = () => {
|
|
||||||
if (isFixed) return;
|
|
||||||
preview.style.display = 'none';
|
|
||||||
};
|
|
||||||
|
|
||||||
hs.onclick = (e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
isFixed = true;
|
|
||||||
updateContent(true);
|
|
||||||
preview.classList.add('fixed-mode');
|
|
||||||
preview.style.display = 'flex';
|
|
||||||
};
|
|
||||||
|
|
||||||
hotspotLayer.appendChild(hs);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 외부 클릭 시 닫기
|
|
||||||
document.addEventListener('click', (e) => {
|
|
||||||
if (!preview.contains(e.target)) {
|
|
||||||
isFixed = false;
|
|
||||||
preview.style.display = 'none';
|
|
||||||
preview.classList.remove('fixed-mode');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -34,8 +34,8 @@ body { background-color: #0b0f1a; font-family: 'Pretendard', sans-serif; margin:
|
|||||||
/* 1. 맵 컨테이너 크기를 rb.layout과 동일하게 1600x980으로 고정 */
|
/* 1. 맵 컨테이너 크기를 rb.layout과 동일하게 1600x980으로 고정 */
|
||||||
.map-container {
|
.map-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 1600px !important;
|
width: 1000px !important;
|
||||||
height: 980px !important;
|
height: 800px !important;
|
||||||
background-size: 100% 100% !important; /* 이미지 늘림 방식을 동일하게 설정 */
|
background-size: 100% 100% !important; /* 이미지 늘림 방식을 동일하게 설정 */
|
||||||
cursor: crosshair;
|
cursor: crosshair;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
@@ -58,7 +58,7 @@ body { background-color: #0b0f1a; font-family: 'Pretendard', sans-serif; margin:
|
|||||||
.map-wrapper {
|
.map-wrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 1600px;
|
width: 1000px;
|
||||||
border-radius: 24px;
|
border-radius: 24px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #161b26;
|
background: #161b26;
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 513 KiB After Width: | Height: | Size: 513 KiB |
|
Before Width: | Height: | Size: 537 KiB After Width: | Height: | Size: 537 KiB |
|
Before Width: | Height: | Size: 496 KiB After Width: | Height: | Size: 496 KiB |
|
Before Width: | Height: | Size: 547 KiB After Width: | Height: | Size: 547 KiB |
|
Before Width: | Height: | Size: 679 KiB After Width: | Height: | Size: 679 KiB |
|
Before Width: | Height: | Size: 512 KiB After Width: | Height: | Size: 512 KiB |
|
Before Width: | Height: | Size: 523 KiB After Width: | Height: | Size: 523 KiB |
|
Before Width: | Height: | Size: 561 KiB After Width: | Height: | Size: 561 KiB |
|
Before Width: | Height: | Size: 562 KiB After Width: | Height: | Size: 562 KiB |
|
Before Width: | Height: | Size: 615 KiB After Width: | Height: | Size: 615 KiB |
|
Before Width: | Height: | Size: 4.1 MiB After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 1.8 MiB |
|
Before Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 221 KiB |
|
Before Width: | Height: | Size: 2.6 MiB |
|
Before Width: | Height: | Size: 2.4 MiB |
|
Before Width: | Height: | Size: 2.5 MiB |
|
Before Width: | Height: | Size: 226 KiB |
|
Before Width: | Height: | Size: 510 KiB |
|
Before Width: | Height: | Size: 645 KiB |
|
Before Width: | Height: | Size: 126 KiB |
|
Before Width: | Height: | Size: 691 KiB |
|
Before Width: | Height: | Size: 949 KiB |
|
Before Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 130 KiB |
|
Before Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 1012 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 136 KiB |
|
Before Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 176 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 319 KiB |
|
Before Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 118 KiB |
|
Before Width: | Height: | Size: 181 KiB |
|
Before Width: | Height: | Size: 202 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |