themblem/scanner/pages/emblemscanner/emblemscanner.wxss
Fam Zheng 0aacad31f4 emblemscanner: add camera rules, web-view fallback, and loading state
Major enhancements to the emblemscanner module:

**Camera System:**
- Device-specific camera rules from Themblem API
- Web-view fallback for problematic devices in same page
- Loading spinner prevents camera mode jumping
- Debug mode with comprehensive diagnostics

**Self-contained Architecture:**
- Inline utility functions (no external dependencies)
- Camera rule matching and API integration
- Web-view URL generation with proper parameters
- Message handling for web-view QR results

**UI Improvements:**
- Hide overlays during loading state
- Enhanced debug overlay with camera rule info
- Worker/native camera mode detection
- Loading feedback with "初始化相机..." message

Module is now production-ready for camera setup and UI, with framework for QR processing integration.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 21:27:29 +00:00

277 lines
4.5 KiB
Plaintext

/* Main container */
view.wrapper {
width: 100%;
height: 100%;
background-size: cover;
position: relative;
overflow: hidden;
}
/* WeChat camera */
camera.camera {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
z-index: -3;
}
/* Web-view camera fallback */
web-view {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
z-index: -3;
}
/* Loading spinner */
.loading-spinner {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #000;
color: white;
z-index: -2;
}
.loading-spinner text {
margin-top: 20rpx;
font-size: 32rpx;
}
/* Canvas for image processing */
canvas#output {
width: 10px;
height: 10px;
position: absolute;
top: 0;
right: 0;
z-index: -10;
}
/* QR targeting arcs overlay */
view.qrarc.sm {
width: 350rpx;
height: 350rpx;
margin: 360rpx 200rpx;
position: absolute;
animation: qrarc-anime 1.2s ease-in-out infinite;
}
view.qrarc.lg {
width: 550rpx;
height: 550rpx;
margin: 260rpx 100rpx;
position: absolute;
animation: qrarc-anime 1.2s ease-in-out infinite;
}
view.qrarc image.arc {
position: absolute;
width: 15%;
height: 15%;
opacity: 0.9;
}
view.qrarc image.arc.topright {
right: 0;
transform: rotate(90deg);
}
view.qrarc image.arc.bottomleft {
bottom: 0;
transform: rotate(-90deg);
}
view.qrarc image.arc.bottomright {
bottom: 0;
right: 0;
transform: rotate(180deg);
}
@keyframes qrarc-anime {
0% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
100% {
transform: scale(1);
}
}
/* QR markers overlay */
view.qrmarkers {
opacity: 70%;
margin: 100rpx 0;
}
image.square {
width: 750rpx;
height: 750rpx;
}
/* On-screen display for hints */
view.osd {
position: fixed;
width: 100%;
top: 0;
color: #fff;
text-align: center;
}
view.osd .upper {
border-radius: 20rpx;
background-color: rgba(0, 0, 0, 0.6);
font-size: 1.1rem;
display: inline-block;
margin: 130rpx auto 630rpx auto;
padding: 0.8rem 2rem;
}
/* Bottom action controls */
view.bottomfixed {
position: absolute;
width: 100%;
bottom: 0;
height: 200rpx;
background-color: #171616;
text-align: center;
border-top: 2px solid rgba(239, 72, 35, 0.7);
color: #707070;
}
.actions {
font-size: 30rpx;
}
.actions .icon image {
height: 30rpx;
width: 80rpx;
}
view.half {
position: relative;
width: 50%;
display: inline-block;
}
view.icon {
font-size: 20rpx;
margin: 30rpx 0 20rpx;
}
view.text {
display: block;
}
view.brighter view.text {
color: #eee;
}
view.brighter {
color: #eee;
}
/* Debug overlay */
view.debug {
position: absolute;
width: 80%;
bottom: 240rpx;
left: 10px;
padding: 0.3rem;
border: 1px solid yellow;
border-radius: 3px;
color: yellow;
background-color: rgba(100, 100, 100, 0.8);
z-index: 1000;
font-size: 13px;
word-break: break-all;
}
view.debug image {
position: fixed;
right: 10px;
top: 10px;
width: 64px;
height: 64px;
border: 1px solid green;
}
/* Tooltip */
view.tooltip {
position: fixed;
bottom: 310rpx;
left: 75rpx;
}
.tooltip-content {
background-color: rgba(0, 0, 0, 0.8);
color: white;
padding: 20rpx;
border-radius: 10rpx;
font-size: 28rpx;
}
/* Modal styles */
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.modal-content {
background-color: white;
padding: 40rpx;
border-radius: 20rpx;
text-align: center;
max-width: 600rpx;
margin: 40rpx;
}
.modal-content.verifying {
display: flex;
flex-direction: column;
align-items: center;
gap: 20rpx;
}
.spinner {
width: 60rpx;
height: 60rpx;
border: 4rpx solid #f3f3f3;
border-top: 4rpx solid #3498db;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.modal-content button {
margin: 20rpx 10rpx;
padding: 20rpx 40rpx;
border: none;
border-radius: 10rpx;
background-color: #ef4823;
color: white;
}