文章目录
-
- 在当今数字化时代,网站设计已成为品牌形象和用户体验的重要组成部分。字体作为视觉传达的核心元素之一,直接影响着网站的可读性、美观性和品牌一致性。然而,大多数网站开发者面临一个共同挑战:如何在保持设计灵活性的同时,确保字体加载效率和跨平台兼容性? 传统的字体管理方法通常依赖于系统默认字体或有限的网络字体库,这限制了设计师的创意表达。随着在线字体库的蓬勃发展,如Google Fonts、Adobe Fonts等提供了数千种高质量字体,但如何高效集成和管理这些资源成为了新的技术难题。 本文将详细介绍如何通过WordPress代码二次开发,集成在线字体库预览与个性化网络字库管理工具,使您的网站拥有专业级的字体管理能力,同时提升用户体验和设计自由度。
-
- 在开始开发之前,我们需要了解WordPress默认的字体处理方式。WordPress核心本身不提供高级字体管理功能,但通过主题和插件可以实现基本的字体控制。常见的方法包括: 主题自定义器中的字体选择器 通过CSS直接引入字体文件 使用插件如"Easy Google Fonts"或"Use Any Font" 然而,这些方法存在局限性:缺乏实时预览、字体库有限、管理不够直观等。我们的目标是创建一个更强大、更灵活的解决方案。
- 为了安全地进行代码二次开发,建议按照以下步骤配置开发环境: 创建子主题:避免直接修改父主题,确保更新不会丢失自定义功能 /* Theme Name: My Custom Theme Template: parent-theme-folder-name */ 启用调试模式:在wp-config.php中设置开发模式 define('WP_DEBUG', true); define('WP_DEBUG_LOG', true); define('WP_DEBUG_DISPLAY', false); 安装必要的开发工具:代码编辑器(如VS Code)、本地服务器环境(如XAMPP或Local by Flywheel)、Git版本控制系统 备份现有网站:在进行任何代码修改前,完整备份网站文件和数据库
- 我们的字体管理工具将采用以下技术架构: 前端:HTML5、CSS3、JavaScript(使用Vue.js或React简化交互开发) 后端:PHP(WordPress核心语言) 数据存储:WordPress自定义数据库表 + 选项API API集成:连接Google Fonts API和其他字体服务API 缓存机制:Transients API提高性能
-
- 我们需要创建自定义数据库表来存储用户字体配置和收藏。在主题的functions.php中添加以下代码: function create_font_management_tables() { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); $table_name = $wpdb->prefix . 'custom_fonts'; $sql = "CREATE TABLE IF NOT EXISTS $table_name ( id mediumint(9) NOT NULL AUTO_INCREMENT, font_name varchar(255) NOT NULL, font_family varchar(255) NOT NULL, font_source varchar(100) DEFAULT 'google', font_variants text, font_subsets text, is_active tinyint(1) DEFAULT 1, created_at datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); // 创建字体使用记录表 $usage_table = $wpdb->prefix . 'font_usage'; $sql_usage = "CREATE TABLE IF NOT EXISTS $usage_table ( id mediumint(9) NOT NULL AUTO_INCREMENT, font_id mediumint(9) NOT NULL, element_type varchar(100), element_selector varchar(255), user_id bigint(20), created_at datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), FOREIGN KEY (font_id) REFERENCES $table_name(id) ON DELETE CASCADE ) $charset_collate;"; dbDelta($sql_usage); } add_action('after_setup_theme', 'create_font_management_tables');
- Google Fonts提供了丰富的免费字体库和易于使用的API。我们将创建一个类来处理与Google Fonts API的交互: class Google_Fonts_Integration { private $api_key = ''; // 可选,如果需要更高API限制 private $api_url = 'https://www.googleapis.com/webfonts/v1/webfonts'; public function __construct() { // 初始化方法 } public function get_all_fonts($sort = 'popularity') { $transient_key = 'google_fonts_list_' . $sort; $fonts = get_transient($transient_key); if (false === $fonts) { $url = $this->api_url . '?sort=' . $sort; if (!empty($this->api_key)) { $url .= '&key=' . $this->api_key; } $response = wp_remote_get($url); if (is_wp_error($response)) { return false; } $body = wp_remote_retrieve_body($response); $data = json_decode($body, true); if (isset($data['items'])) { $fonts = $data['items']; set_transient($transient_key, $fonts, WEEK_IN_SECONDS); } } return $fonts; } public function generate_font_import_url($font_family, $variants = array(), $subsets = array()) { $base_url = 'https://fonts.googleapis.com/css2'; $family_param = urlencode($font_family); if (!empty($variants)) { $variant_str = implode(',', $variants); $family_param .= ':wght@' . $variant_str; } $query_args = array('family' => $family_param); if (!empty($subsets)) { $query_args['subset'] = implode(',', $subsets); } return add_query_arg($query_args, $base_url); } }
- 实时预览是字体管理工具的核心功能。我们将创建一个交互式预览界面: function enqueue_font_preview_assets() { // 仅在需要字体管理的页面加载资源 if (is_admin() || current_user_can('edit_theme_options')) { wp_enqueue_style('font-preview-admin', get_template_directory_uri() . '/css/font-preview.css'); wp_enqueue_script('vue-js', 'https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js', array(), '2.6.14', true); wp_enqueue_script('font-preview-app', get_template_directory_uri() . '/js/font-preview.js', array('vue-js', 'jquery'), '1.0.0', true); // 传递数据到JavaScript wp_localize_script('font-preview-app', 'fontPreviewData', array( 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('font_preview_nonce'), 'default_text' => __('The quick brown fox jumps over the lazy dog', 'textdomain'), 'font_categories' => array('serif', 'sans-serif', 'display', 'handwriting', 'monospace') )); } } add_action('admin_enqueue_scripts', 'enqueue_font_preview_assets'); 创建预览界面的HTML结构: <div id="font-preview-app" class="font-management-wrapper"> <div class="font-preview-container"> <div class="font-controls"> <div class="font-search"> <input type="text" v-model="searchQuery" placeholder="搜索字体..."> <select v-model="selectedCategory"> <option value="">所有分类</option> <option v-for="category in categories" :value="category">{{ category }}</option> </select> <select v-model="selectedSort"> <option value="popularity">最受欢迎</option> <option value="trending">趋势</option> <option value="alpha">字母顺序</option> </select> </div> <div class="preview-controls"> <div class="text-input"> <textarea v-model="previewText" placeholder="输入预览文本"></textarea> </div> <div class="size-control"> <label>字体大小:</label> <input type="range" v-model="fontSize" min="12" max="72" step="1"> <span>{{ fontSize }}px</span> </div> </div> </div> <div class="font-grid"> <div v-for="font in filteredFonts" :key="font.family" class="font-card" :class="{ active: isFontActive(font.family) }"> <div class="font-preview" :style="{ fontFamily: font.family, fontSize: fontSize + 'px' }"> {{ previewText || defaultText }} </div> <div class="font-info"> <h3>{{ font.family }}</h3> <div class="font-actions"> <button @click="toggleFont(font)" class="button"> {{ isFontActive(font.family) ? '已启用' : '启用' }} </button> <button @click="showVariants(font)" class="button button-secondary"> 变体 </button> </div> </div> </div> </div> <div class="pagination" v-if="totalPages > 1"> <button @click="prevPage" :disabled="currentPage === 1">上一页</button> <span>第 {{ currentPage }} 页,共 {{ totalPages }} 页</span> <button @click="nextPage" :disabled="currentPage === totalPages">下一页</button> </div> </div> <!-- 字体变体选择模态框 --> <div v-if="showVariantModal" class="modal-overlay"> <div class="modal-content"> <h2>选择字体变体: {{ selectedFont.family }}</h2> <div class="variant-grid"> <div v-for="variant in selectedFont.variants" :key="variant" class="variant-option"> <input type="checkbox" :id="'variant-' + variant" :value="variant" v-model="selectedVariants"> <label :for="'variant-' + variant" :style="{ fontFamily: selectedFont.family, fontWeight: variant }"> {{ getVariantName(variant) }} </label> </div> </div> <div class="modal-actions"> <button @click="applyVariants" class="button button-primary">应用</button> <button @click="closeModal" class="button">取消</button> </div> </div> </div> </div>
-
- 在WordPress后台添加自定义菜单页面,用于管理字体: function add_font_management_page() { add_menu_page( '字体管理', '字体管理', 'manage_options', 'font-management', 'render_font_management_page', 'dashicons-editor-textcolor', 30 ); add_submenu_page( 'font-management', '我的字体库', '我的字体库', 'manage_options', 'font-library', 'render_font_library_page' ); add_submenu_page( 'font-management', '字体设置', '字体设置', 'manage_options', 'font-settings', 'render_font_settings_page' ); } add_action('admin_menu', 'add_font_management_page'); function render_font_management_page() { ?> <div class="wrap"> <h1><?php echo esc_html(get_admin_page_title()); ?></h1> <div id="font-management-app"> <!-- 这里将加载Vue.js应用 --> </div> </div> <?php }
- 处理字体启用/禁用、保存配置等操作: // 处理字体启用/禁用 add_action('wp_ajax_toggle_font', 'handle_toggle_font'); function handle_toggle_font() { // 验证nonce if (!wp_verify_nonce($_POST['nonce'], 'font_preview_nonce')) { wp_die('安全验证失败'); } $font_family = sanitize_text_field($_POST['font_family']); $variants = isset($_POST['variants']) ? array_map('sanitize_text_field', $_POST['variants']) : array('regular'); $action = sanitize_text_field($_POST['action_type']); // 'enable' 或 'disable' global $wpdb; $table_name = $wpdb->prefix . 'custom_fonts'; if ($action === 'enable') { // 检查是否已存在 $existing = $wpdb->get_var($wpdb->prepare( "SELECT id FROM $table_name WHERE font_family = %s", $font_family )); if (!$existing) { $wpdb->insert( $table_name, array( 'font_name' => $font_family, 'font_family' => $font_family, 'font_variants' => json_encode($variants), 'is_active' => 1 ), array('%s', '%s', '%s', '%d') ); } else { $wpdb->update( $table_name, array('is_active' => 1, 'font_variants' => json_encode($variants)), array('id' => $existing), array('%d', '%s'), array('%d') ); } // 更新CSS文件 update_font_css_file(); wp_send_json_success(array('message' => '字体已启用')); } else { $wpdb->update( $table_name, array('is_active' => 0), array('font_family' => $font_family), array('%d'), array('%s') ); update_font_css_file(); wp_send_json_success(array('message' => '字体已禁用')); } } // 更新字体CSS文件 function update_font_css_file() { global $wpdb; $table_name = $wpdb->prefix . 'custom_fonts'; $active_fonts = $wpdb->get_results( "SELECT font_family, font_variants, font_source FROM $table_name WHERE is_active = 1" ); $css_content = "/* 动态生成的字体CSS - 最后更新: " . date('Y-m-d H:i:s') . " */nn"; foreach ($active_fonts as $font) { $variants = json_decode($font->font_variants, true); if ($font->font_source === 'google') { $font_integration = new Google_Fonts_Integration(); $import_url = $font_integration->generate_font_import_url($font->font_family, $variants); $css_content .= "@import url('" . esc_url($import_url) . "');n"; } // 为每个字体生成CSS类 $font_class = sanitize_title($font->font_family); $css_content .= ".font-" . $font_class . " { font-family: '" . $font->font_family . "', sans-serif; }n"; } // 保存到文件 $upload_dir = wp_upload_dir(); $font_css_path = $upload_dir['basedir'] . '/dynamic-fonts.css'; file_put_contents($font_css_path, $css_content); // 更新选项记录文件路径 update_option('dynamic_font_css_path', $upload_dir['baseurl'] . '/dynamic-fonts.css'); }
- 除了在线字体库,用户可能希望上传自己的字体文件: function handle_custom_font_upload() { if (!current_user_can('upload_files')) { wp_die('权限不足'); } if (!wp_verify_nonce($_POST['_wpnonce'], 'custom_font_upload')) { wp_die('安全验证失败'); } $font_file = $_FILES['font_file']; // 检查文件类型 $allowed_types = array('ttf', 'otf', 'woff', 'woff2', 'eot'); $file_ext = pathinfo($font_file['name'], PATHINFO_EXTENSION); if (!in_array(strtolower($file_ext), $allowed_types)) { wp_send_json_error(array('message' => '不支持的文件类型')); } // 处理上传 require_once(ABSPATH . 'wp-admin/includes/file.php'); $upload_overrides = array('test_form' => false); $movefile = wp_handle_upload($font_file, $upload_overrides); if ($movefile && !isset($movefile['error'])) { // 保存字体信息到数据库 $font_name = sanitize_text_field($_POST['font_name']); $font_family = !empty($_POST['font_family']) ? sanitize_text_field($_POST['font_family']) : $font_name; global $wpdb; $table_name = $wpdb->prefix . 'custom_fonts'; $wpdb->insert( $table_name, array( 'font_name' => $font_name, 'font_family' => $font_family, 'font_source' => 'custom', 'font_variants' => json_encode(array('regular', 'bold')), 'font_file_url' => $movefile['url'], 'is_active' => 1 ), array('%s', '%s', '%s', '%s', '%s', '%d') ); // 生成@font-face规则 generate_custom_fontface_css($font_family, $movefile['url'], $file_ext); wp_send_json_success(array( 'message' => '字体上传成功', 'font_family' => $font_family, 'file_url' => $movefile['url'] )); } else { wp_send_json_error(array('message' => $movefile['error'])); } } add_action('wp_ajax_upload_custom_font', 'handle_custom_font_upload'); function generate_custom_fontface_css($font_family, $font_url, $font_ext) { $css_content = "n/* 自定义字体: " . $font_family . " */n"; $css_content .= "@font-face {n"; $css_content .= " font-family: '" . $font_family . "';n"; $css_content .= " src: url('" . $font_url . "') format('" . get_font_format($font_ext) . "');n"; $css_content .= " font-weight: normal;n"; $css_content .= " font-style: normal;n"; $css_content .= " font-display: swap;n"; $css_content .= "}nn"; // 追加到动态字体CSS文件 $upload_dir = wp_upload_dir(); $font_css_path = $upload_dir['basedir'] . '/dynamic-fonts.css'; if (file_exists($font_css_path)) { file_put_contents($font_css_path, $css_content, FILE_APPEND); } } function get_font_format($extension) { $formats = array( 'ttf' => 'truetype', 'otf' => 'opentype', 'woff' => 'woff', 'woff2' => 'woff2', 'eot' => 'embedded-opentype' ); return isset($formats[strtolower($extension)]) ? $formats[strtolower($extension)] : 'truetype'; }
-
- 字体加载是影响网站性能的关键因素。我们将实施多种优化策略: class Font_Performance_Optimizer { public function __construct() { add_action('wp_head', array($this, 'add_font_preload_tags'), 1); add_action('wp_enqueue_scripts', array($this, 'optimize_font_loading')); } public function add_font_preload_tags() { $active_fonts = $this->get_critical_fonts(); foreach ($active_fonts as $font) { if ($font['source'] === 'google') { // 预加载关键字体文件 echo '<link rel="preload" as="style" href="' . esc_url($font['url']) . '" crossorigin>'; // 添加预连接到Google Fonts域名 echo '<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>'; } elseif ($font['source'] === 'custom') { echo '<link rel="preload" as="font" href="' . esc_url($font['url']) . '" type="font/' . esc_attr($font['format']) . '" crossorigin>'; } } } public function optimize_font_loading() { // 延迟加载非关键字体 $font_css_url = get_option('dynamic_font_css_path'); if ($font_css_url) { // 使用media="print"技巧延迟加载 wp_register_style('dynamic-fonts-print', $font_css_url, array(), null, 'print'); wp_enqueue_style('dynamic-fonts-print'); // 加载后切换到all媒体类型 wp_add_inline_script('jquery', ' (function() { var fontStylesheet = document.querySelector("link[media='print']"); if (fontStylesheet) { fontStylesheet.media = "all"; } })(); '); } } private function get_critical_fonts() { global $wpdb; $table_name = $wpdb->prefix . 'custom_fonts'; $fonts = $wpdb->get_results( "SELECT font_family, font_source, font_file_url FROM $table_name WHERE is_active = 1 AND is_critical = 1", ARRAY_A ); return $fonts; } // 实现字体缓存机制 public static function cache_font_files($font_url, $font_family) { $upload_dir = wp_upload_dir(); $cache_dir = $upload_dir['basedir'] . '/font-cache/'; // 创建缓存目录 if (!file_exists($cache_dir)) { wp_mkdir_p($cache_dir); } $cache_key = md5($font_url . $font_family); $cache_file = $cache_dir . $cache_key . '.css'; // 检查缓存是否有效(24小时) if (file_exists($cache_file) && (time() - filemtime($cache_file)) < DAY_IN_SECONDS) { return str_replace($upload_dir['basedir'], $upload_dir['baseurl'], $cache_file); } // 下载并缓存字体CSS $response = wp_remote_get($font_url); if (!is_wp_error($response)) { $font_css = wp_remote_retrieve_body($response); // 本地化字体文件URL $font_css = self::localize_font_urls($font_css, $font_family); file_put_contents($cache_file, $font_css); return str_replace($upload_dir['basedir'], $upload_dir['baseurl'], $cache_file); } return $font_url; // 失败时返回原始URL } private static function localize_font_urls($css_content, $font_family) { // 匹配字体URL并下载到本地 preg_match_all('/url((https?://[^)]+))/', $css_content, $matches); if (!empty($matches[1])) { $upload_dir = wp_upload_dir(); $font_dir = $upload_dir['basedir'] . '/fonts/' . sanitize_title($font_family) . '/'; if (!file_exists($font_dir)) { wp_mkdir_p($font_dir); } foreach ($matches[1] as $font_url) { $font_filename = basename(parse_url($font_url, PHP_URL_PATH)); $local_font_path = $font_dir . $font_filename; // 下载字体文件 if (!file_exists($local_font_path)) { $font_data = wp_remote_get($font_url); if (!is_wp_error($font_data)) { file_put_contents($local_font_path, wp_remote_retrieve_body($font_data)); } } // 替换URL为本地路径 $local_font_url = str_replace( $upload_dir['basedir'], $upload_dir['baseurl'], $local_font_path ); $css_content = str_replace($font_url, $local_font_url, $css_content); } } return $css_content; } } new Font_Performance_Optimizer();
- 了解字体使用情况有助于优化决策: class Font_Analytics { public function __construct() { add_action('wp_footer', array($this, 'track_font_usage')); add_action('admin_menu', array($this, 'add_analytics_page')); } public function track_font_usage() { if (!current_user_can('manage_options')) { return; } ?> <script> (function() { // 检测页面中使用的字体 var usedFonts = new Set(); // 检查所有元素的计算字体 var allElements = document.querySelectorAll('*'); allElements.forEach(function(el) { var computedStyle = window.getComputedStyle(el); var fontFamily = computedStyle.fontFamily; if (fontFamily && fontFamily !== 'inherit') { // 提取字体族名称(去除引号和备用字体) var fonts = fontFamily.split(',')[0].replace(/['"]/g, '').trim(); if (fonts) { usedFonts.add(fonts); } } }); // 发送使用数据到服务器 if (usedFonts.size > 0) { var data = { action: 'track_font_usage', fonts: Array.from(usedFonts), page_url: window.location.href, nonce: '<?php echo wp_create_nonce("font_analytics_nonce"); ?>' }; // 使用navigator.sendBeacon确保数据发送 if (navigator.sendBeacon) { var formData = new FormData(); for (var key in data) { formData.append(key, data[key]); } navigator.sendBeacon('<?php echo admin_url("admin-ajax.php"); ?>', formData); } } })(); </script> <?php } public static function handle_usage_tracking() { if (!wp_verify_nonce($_POST['nonce'], 'font_analytics_nonce')) { wp_die('安全验证失败'); } $fonts = isset($_POST['fonts']) ? array_map('sanitize_text_field', $_POST['fonts']) : array(); $page_url = sanitize_url($_POST['page_url']); $user_id = get_current_user_id(); global $wpdb; $usage_table = $wpdb->prefix . 'font_usage'; $fonts_table = $wpdb->prefix . 'custom_fonts'; foreach ($fonts as $font_family) { // 查找字体ID $font_id = $wpdb->get_var($wpdb->prepare( "SELECT id FROM $fonts_table WHERE font_family = %s", $font_family )); if ($font_id) { // 记录使用情况 $wpdb->insert( $usage_table, array( 'font_id' => $font_id, 'page_url' => $page_url, 'user_id' => $user_id ), array('%d', '%s', '%d') ); } } wp_die(); } public function add_analytics_page() { add_submenu_page( 'font-management', '字体分析', '字体分析', 'manage_options', 'font-analytics', array($this, 'render_analytics_page') ); } public function render_analytics_page() { ?> <div class="wrap"> <h1>字体使用分析</h1> <div class="analytics-container"> <div class="analytics-stats"> <?php $this->display_font_statistics(); ?> </div> <div class="analytics-charts"> <canvas id="fontUsageChart" width="400" height="200"></canvas> </div> <div class="analytics-table"> <?php $this->display_font_usage_table(); ?> </div> </div> </div> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script> jQuery(document).ready(function($) { var ctx = document.getElementById('fontUsageChart').getContext('2d'); var chart = new Chart(ctx, { type: 'bar', data: { labels: <?php echo json_encode($this->get_font_labels()); ?>, datasets: [{ label: '使用次数', data: <?php echo json_encode($this->get_font_usage_data()); ?>, backgroundColor: 'rgba(54, 162, 235, 0.5)', borderColor: 'rgba(54, 162, 235, 1)', borderWidth: 1 }] }, options: { responsive: true, scales: { y: { beginAtZero: true } } } }); }); </script> <?php } private function display_font_statistics() { global $wpdb; $fonts_table = $wpdb->prefix . 'custom_fonts'; $usage_table = $wpdb->prefix . 'font_usage'; $total_fonts = $wpdb->get_var("SELECT COUNT(*) FROM $fonts_table WHERE is_active = 1"); $total_usage = $wpdb->get_var("SELECT COUNT(*) FROM $usage_table"); $most_used = $wpdb->get_row( "SELECT f.font_family, COUNT(u.id) as usage_count FROM $usage_table u JOIN $fonts_table f ON u.font_id = f.id GROUP BY u.font_id ORDER BY usage_count DESC LIMIT 1" ); echo '<div class="stat-card">'; echo '<h3>活跃字体数量</h3>'; echo '<p class="stat-number">' . $total_fonts . '</p>'; echo '</div>'; echo '<div class="stat-card">'; echo '<h3>总使用次数</h3>'; echo '<p class="stat-number">' . $total_usage . '</p>'; echo '</div>'; if ($most_used) { echo '<div class="stat-card">'; echo '<h3>最常用字体</h3>'; echo '<p class="stat-number">' . esc_html($most_used->font_family) . '</p>'; echo '<p class="stat-desc">使用次数: ' . $most_used->usage_count . '</p>'; echo '</div>'; } } } add_action('wp_ajax_track_font_usage', array('Font_Analytics', 'handle_usage_tracking')); add_action('wp_ajax_nopriv_track_font_usage', array('Font_Analytics', 'handle_usage_tracking'));
在当今数字化时代,网站设计已成为品牌形象和用户体验的重要组成部分。字体作为视觉传达的核心元素之一,直接影响着网站的可读性、美观性和品牌一致性。然而,大多数网站开发者面临一个共同挑战:如何在保持设计灵活性的同时,确保字体加载效率和跨平台兼容性?
传统的字体管理方法通常依赖于系统默认字体或有限的网络字体库,这限制了设计师的创意表达。随着在线字体库的蓬勃发展,如Google Fonts、Adobe Fonts等提供了数千种高质量字体,但如何高效集成和管理这些资源成为了新的技术难题。
本文将详细介绍如何通过WordPress代码二次开发,集成在线字体库预览与个性化网络字库管理工具,使您的网站拥有专业级的字体管理能力,同时提升用户体验和设计自由度。
在开始开发之前,我们需要了解WordPress默认的字体处理方式。WordPress核心本身不提供高级字体管理功能,但通过主题和插件可以实现基本的字体控制。常见的方法包括:
- 主题自定义器中的字体选择器
- 通过CSS直接引入字体文件
- 使用插件如"Easy Google Fonts"或"Use Any Font"
然而,这些方法存在局限性:缺乏实时预览、字体库有限、管理不够直观等。我们的目标是创建一个更强大、更灵活的解决方案。
为了安全地进行代码二次开发,建议按照以下步骤配置开发环境:
-
创建子主题:避免直接修改父主题,确保更新不会丢失自定义功能
/* Theme Name: My Custom Theme Template: parent-theme-folder-name */ -
启用调试模式:在wp-config.php中设置开发模式
define('WP_DEBUG', true); define('WP_DEBUG_LOG', true); define('WP_DEBUG_DISPLAY', false); - 安装必要的开发工具:代码编辑器(如VS Code)、本地服务器环境(如XAMPP或Local by Flywheel)、Git版本控制系统
- 备份现有网站:在进行任何代码修改前,完整备份网站文件和数据库
我们的字体管理工具将采用以下技术架构:
- 前端:HTML5、CSS3、JavaScript(使用Vue.js或React简化交互开发)
- 后端:PHP(WordPress核心语言)
- 数据存储:WordPress自定义数据库表 + 选项API
- API集成:连接Google Fonts API和其他字体服务API
- 缓存机制:Transients API提高性能
我们需要创建自定义数据库表来存储用户字体配置和收藏。在主题的functions.php中添加以下代码:
function create_font_management_tables() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$table_name = $wpdb->prefix . 'custom_fonts';
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
font_name varchar(255) NOT NULL,
font_family varchar(255) NOT NULL,
font_source varchar(100) DEFAULT 'google',
font_variants text,
font_subsets text,
is_active tinyint(1) DEFAULT 1,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
// 创建字体使用记录表
$usage_table = $wpdb->prefix . 'font_usage';
$sql_usage = "CREATE TABLE IF NOT EXISTS $usage_table (
id mediumint(9) NOT NULL AUTO_INCREMENT,
font_id mediumint(9) NOT NULL,
element_type varchar(100),
element_selector varchar(255),
user_id bigint(20),
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
FOREIGN KEY (font_id) REFERENCES $table_name(id) ON DELETE CASCADE
) $charset_collate;";
dbDelta($sql_usage);
}
add_action('after_setup_theme', 'create_font_management_tables');
Google Fonts提供了丰富的免费字体库和易于使用的API。我们将创建一个类来处理与Google Fonts API的交互:
class Google_Fonts_Integration {
private $api_key = ''; // 可选,如果需要更高API限制
private $api_url = 'https://www.googleapis.com/webfonts/v1/webfonts';
public function __construct() {
// 初始化方法
}
public function get_all_fonts($sort = 'popularity') {
$transient_key = 'google_fonts_list_' . $sort;
$fonts = get_transient($transient_key);
if (false === $fonts) {
$url = $this->api_url . '?sort=' . $sort;
if (!empty($this->api_key)) {
$url .= '&key=' . $this->api_key;
}
$response = wp_remote_get($url);
if (is_wp_error($response)) {
return false;
}
$body = wp_remote_retrieve_body($response);
$data = json_decode($body, true);
if (isset($data['items'])) {
$fonts = $data['items'];
set_transient($transient_key, $fonts, WEEK_IN_SECONDS);
}
}
return $fonts;
}
public function generate_font_import_url($font_family, $variants = array(), $subsets = array()) {
$base_url = 'https://fonts.googleapis.com/css2';
$family_param = urlencode($font_family);
if (!empty($variants)) {
$variant_str = implode(',', $variants);
$family_param .= ':wght@' . $variant_str;
}
$query_args = array('family' => $family_param);
if (!empty($subsets)) {
$query_args['subset'] = implode(',', $subsets);
}
return add_query_arg($query_args, $base_url);
}
}
实时预览是字体管理工具的核心功能。我们将创建一个交互式预览界面:
function enqueue_font_preview_assets() {
// 仅在需要字体管理的页面加载资源
if (is_admin() || current_user_can('edit_theme_options')) {
wp_enqueue_style('font-preview-admin', get_template_directory_uri() . '/css/font-preview.css');
wp_enqueue_script('vue-js', 'https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js', array(), '2.6.14', true);
wp_enqueue_script('font-preview-app', get_template_directory_uri() . '/js/font-preview.js', array('vue-js', 'jquery'), '1.0.0', true);
// 传递数据到JavaScript
wp_localize_script('font-preview-app', 'fontPreviewData', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('font_preview_nonce'),
'default_text' => __('The quick brown fox jumps over the lazy dog', 'textdomain'),
'font_categories' => array('serif', 'sans-serif', 'display', 'handwriting', 'monospace')
));
}
}
add_action('admin_enqueue_scripts', 'enqueue_font_preview_assets');
创建预览界面的HTML结构:
<div id="font-preview-app" class="font-management-wrapper">
<div class="font-preview-container">
<div class="font-controls">
<div class="font-search">
<input type="text" v-model="searchQuery" placeholder="搜索字体...">
<select v-model="selectedCategory">
<option value="">所有分类</option>
<option v-for="category in categories" :value="category">{{ category }}</option>
</select>
<select v-model="selectedSort">
<option value="popularity">最受欢迎</option>
<option value="trending">趋势</option>
<option value="alpha">字母顺序</option>
</select>
</div>
<div class="preview-controls">
<div class="text-input">
<textarea v-model="previewText" placeholder="输入预览文本"></textarea>
</div>
<div class="size-control">
<label>字体大小:</label>
<input type="range" v-model="fontSize" min="12" max="72" step="1">
<span>{{ fontSize }}px</span>
</div>
</div>
</div>
<div class="font-grid">
<div v-for="font in filteredFonts" :key="font.family" class="font-card" :class="{ active: isFontActive(font.family) }">
<div class="font-preview" :style="{ fontFamily: font.family, fontSize: fontSize + 'px' }">
{{ previewText || defaultText }}
</div>
<div class="font-info">
<h3>{{ font.family }}</h3>
<div class="font-actions">
<button @click="toggleFont(font)" class="button">
{{ isFontActive(font.family) ? '已启用' : '启用' }}
</button>
<button @click="showVariants(font)" class="button button-secondary">
变体
</button>
</div>
</div>
</div>
</div>
<div class="pagination" v-if="totalPages > 1">
<button @click="prevPage" :disabled="currentPage === 1">上一页</button>
<span>第 {{ currentPage }} 页,共 {{ totalPages }} 页</span>
<button @click="nextPage" :disabled="currentPage === totalPages">下一页</button>
</div>
</div>
<!-- 字体变体选择模态框 -->
<div v-if="showVariantModal" class="modal-overlay">
<div class="modal-content">
<h2>选择字体变体: {{ selectedFont.family }}</h2>
<div class="variant-grid">
<div v-for="variant in selectedFont.variants" :key="variant" class="variant-option">
<input type="checkbox" :id="'variant-' + variant" :value="variant" v-model="selectedVariants">
<label :for="'variant-' + variant" :style="{ fontFamily: selectedFont.family, fontWeight: variant }">
{{ getVariantName(variant) }}
</label>
</div>
</div>
<div class="modal-actions">
<button @click="applyVariants" class="button button-primary">应用</button>
<button @click="closeModal" class="button">取消</button>
</div>
</div>
</div>
</div>
在WordPress后台添加自定义菜单页面,用于管理字体:
function add_font_management_page() {
add_menu_page(
'字体管理',
'字体管理',
'manage_options',
'font-management',
'render_font_management_page',
'dashicons-editor-textcolor',
30
);
add_submenu_page(
'font-management',
'我的字体库',
'我的字体库',
'manage_options',
'font-library',
'render_font_library_page'
);
add_submenu_page(
'font-management',
'字体设置',
'字体设置',
'manage_options',
'font-settings',
'render_font_settings_page'
);
}
add_action('admin_menu', 'add_font_management_page');
function render_font_management_page() {
?>
<div class="wrap">
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
<div id="font-management-app">
<!-- 这里将加载Vue.js应用 -->
</div>
</div>
<?php
}
处理字体启用/禁用、保存配置等操作:
// 处理字体启用/禁用
add_action('wp_ajax_toggle_font', 'handle_toggle_font');
function handle_toggle_font() {
// 验证nonce
if (!wp_verify_nonce($_POST['nonce'], 'font_preview_nonce')) {
wp_die('安全验证失败');
}
$font_family = sanitize_text_field($_POST['font_family']);
$variants = isset($_POST['variants']) ? array_map('sanitize_text_field', $_POST['variants']) : array('regular');
$action = sanitize_text_field($_POST['action_type']); // 'enable' 或 'disable'
global $wpdb;
$table_name = $wpdb->prefix . 'custom_fonts';
if ($action === 'enable') {
// 检查是否已存在
$existing = $wpdb->get_var($wpdb->prepare(
"SELECT id FROM $table_name WHERE font_family = %s",
$font_family
));
if (!$existing) {
$wpdb->insert(
$table_name,
array(
'font_name' => $font_family,
'font_family' => $font_family,
'font_variants' => json_encode($variants),
'is_active' => 1
),
array('%s', '%s', '%s', '%d')
);
} else {
$wpdb->update(
$table_name,
array('is_active' => 1, 'font_variants' => json_encode($variants)),
array('id' => $existing),
array('%d', '%s'),
array('%d')
);
}
// 更新CSS文件
update_font_css_file();
wp_send_json_success(array('message' => '字体已启用'));
} else {
$wpdb->update(
$table_name,
array('is_active' => 0),
array('font_family' => $font_family),
array('%d'),
array('%s')
);
update_font_css_file();
wp_send_json_success(array('message' => '字体已禁用'));
}
}
// 更新字体CSS文件
function update_font_css_file() {
global $wpdb;
$table_name = $wpdb->prefix . 'custom_fonts';
$active_fonts = $wpdb->get_results(
"SELECT font_family, font_variants, font_source FROM $table_name WHERE is_active = 1"
);
$css_content = "/* 动态生成的字体CSS - 最后更新: " . date('Y-m-d H:i:s') . " */nn";
foreach ($active_fonts as $font) {
$variants = json_decode($font->font_variants, true);
if ($font->font_source === 'google') {
$font_integration = new Google_Fonts_Integration();
$import_url = $font_integration->generate_font_import_url($font->font_family, $variants);
$css_content .= "@import url('" . esc_url($import_url) . "');n";
}
// 为每个字体生成CSS类
$font_class = sanitize_title($font->font_family);
$css_content .= ".font-" . $font_class . " { font-family: '" . $font->font_family . "', sans-serif; }n";
}
// 保存到文件
$upload_dir = wp_upload_dir();
$font_css_path = $upload_dir['basedir'] . '/dynamic-fonts.css';
file_put_contents($font_css_path, $css_content);
// 更新选项记录文件路径
update_option('dynamic_font_css_path', $upload_dir['baseurl'] . '/dynamic-fonts.css');
}
除了在线字体库,用户可能希望上传自己的字体文件:
function handle_custom_font_upload() {
if (!current_user_can('upload_files')) {
wp_die('权限不足');
}
if (!wp_verify_nonce($_POST['_wpnonce'], 'custom_font_upload')) {
wp_die('安全验证失败');
}
$font_file = $_FILES['font_file'];
// 检查文件类型
$allowed_types = array('ttf', 'otf', 'woff', 'woff2', 'eot');
$file_ext = pathinfo($font_file['name'], PATHINFO_EXTENSION);
if (!in_array(strtolower($file_ext), $allowed_types)) {
wp_send_json_error(array('message' => '不支持的文件类型'));
}
// 处理上传
require_once(ABSPATH . 'wp-admin/includes/file.php');
$upload_overrides = array('test_form' => false);
$movefile = wp_handle_upload($font_file, $upload_overrides);
if ($movefile && !isset($movefile['error'])) {
// 保存字体信息到数据库
$font_name = sanitize_text_field($_POST['font_name']);
$font_family = !empty($_POST['font_family']) ?
sanitize_text_field($_POST['font_family']) : $font_name;
global $wpdb;
$table_name = $wpdb->prefix . 'custom_fonts';
$wpdb->insert(
$table_name,
array(
'font_name' => $font_name,
'font_family' => $font_family,
'font_source' => 'custom',
'font_variants' => json_encode(array('regular', 'bold')),
'font_file_url' => $movefile['url'],
'is_active' => 1
),
array('%s', '%s', '%s', '%s', '%s', '%d')
);
// 生成@font-face规则
generate_custom_fontface_css($font_family, $movefile['url'], $file_ext);
wp_send_json_success(array(
'message' => '字体上传成功',
'font_family' => $font_family,
'file_url' => $movefile['url']
));
} else {
wp_send_json_error(array('message' => $movefile['error']));
}
}
add_action('wp_ajax_upload_custom_font', 'handle_custom_font_upload');
function generate_custom_fontface_css($font_family, $font_url, $font_ext) {
$css_content = "n/* 自定义字体: " . $font_family . " */n";
$css_content .= "@font-face {n";
$css_content .= " font-family: '" . $font_family . "';n";
$css_content .= " src: url('" . $font_url . "') format('" . get_font_format($font_ext) . "');n";
$css_content .= " font-weight: normal;n";
$css_content .= " font-style: normal;n";
$css_content .= " font-display: swap;n";
$css_content .= "}nn";
// 追加到动态字体CSS文件
$upload_dir = wp_upload_dir();
$font_css_path = $upload_dir['basedir'] . '/dynamic-fonts.css';
if (file_exists($font_css_path)) {
file_put_contents($font_css_path, $css_content, FILE_APPEND);
}
}
function get_font_format($extension) {
$formats = array(
'ttf' => 'truetype',
'otf' => 'opentype',
'woff' => 'woff',
'woff2' => 'woff2',
'eot' => 'embedded-opentype'
);
return isset($formats[strtolower($extension)]) ?
$formats[strtolower($extension)] : 'truetype';
}
字体加载是影响网站性能的关键因素。我们将实施多种优化策略:
class Font_Performance_Optimizer {
public function __construct() {
add_action('wp_head', array($this, 'add_font_preload_tags'), 1);
add_action('wp_enqueue_scripts', array($this, 'optimize_font_loading'));
}
public function add_font_preload_tags() {
$active_fonts = $this->get_critical_fonts();
foreach ($active_fonts as $font) {
if ($font['source'] === 'google') {
// 预加载关键字体文件
echo '<link rel="preload" as="style" href="' .
esc_url($font['url']) . '" crossorigin>';
// 添加预连接到Google Fonts域名
echo '<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>';
} elseif ($font['source'] === 'custom') {
echo '<link rel="preload" as="font" href="' .
esc_url($font['url']) . '" type="font/' .
esc_attr($font['format']) . '" crossorigin>';
}
}
}
public function optimize_font_loading() {
// 延迟加载非关键字体
$font_css_url = get_option('dynamic_font_css_path');
if ($font_css_url) {
// 使用media="print"技巧延迟加载
wp_register_style('dynamic-fonts-print', $font_css_url, array(), null, 'print');
wp_enqueue_style('dynamic-fonts-print');
// 加载后切换到all媒体类型
wp_add_inline_script('jquery', '
(function() {
var fontStylesheet = document.querySelector("link[media='print']");
if (fontStylesheet) {
fontStylesheet.media = "all";
}
})();
');
}
}
private function get_critical_fonts() {
global $wpdb;
$table_name = $wpdb->prefix . 'custom_fonts';
$fonts = $wpdb->get_results(
"SELECT font_family, font_source, font_file_url FROM $table_name
WHERE is_active = 1 AND is_critical = 1",
ARRAY_A
);
return $fonts;
}
// 实现字体缓存机制
public static function cache_font_files($font_url, $font_family) {
$upload_dir = wp_upload_dir();
$cache_dir = $upload_dir['basedir'] . '/font-cache/';
// 创建缓存目录
if (!file_exists($cache_dir)) {
wp_mkdir_p($cache_dir);
}
$cache_key = md5($font_url . $font_family);
$cache_file = $cache_dir . $cache_key . '.css';
// 检查缓存是否有效(24小时)
if (file_exists($cache_file) &&
(time() - filemtime($cache_file)) < DAY_IN_SECONDS) {
return str_replace($upload_dir['basedir'], $upload_dir['baseurl'], $cache_file);
}
// 下载并缓存字体CSS
$response = wp_remote_get($font_url);
if (!is_wp_error($response)) {
$font_css = wp_remote_retrieve_body($response);
// 本地化字体文件URL
$font_css = self::localize_font_urls($font_css, $font_family);
file_put_contents($cache_file, $font_css);
return str_replace($upload_dir['basedir'], $upload_dir['baseurl'], $cache_file);
}
return $font_url; // 失败时返回原始URL
}
private static function localize_font_urls($css_content, $font_family) {
// 匹配字体URL并下载到本地
preg_match_all('/url((https?://[^)]+))/', $css_content, $matches);
if (!empty($matches[1])) {
$upload_dir = wp_upload_dir();
$font_dir = $upload_dir['basedir'] . '/fonts/' . sanitize_title($font_family) . '/';
if (!file_exists($font_dir)) {
wp_mkdir_p($font_dir);
}
foreach ($matches[1] as $font_url) {
$font_filename = basename(parse_url($font_url, PHP_URL_PATH));
$local_font_path = $font_dir . $font_filename;
// 下载字体文件
if (!file_exists($local_font_path)) {
$font_data = wp_remote_get($font_url);
if (!is_wp_error($font_data)) {
file_put_contents($local_font_path, wp_remote_retrieve_body($font_data));
}
}
// 替换URL为本地路径
$local_font_url = str_replace(
$upload_dir['basedir'],
$upload_dir['baseurl'],
$local_font_path
);
$css_content = str_replace($font_url, $local_font_url, $css_content);
}
}
return $css_content;
}
}
new Font_Performance_Optimizer();
了解字体使用情况有助于优化决策:
class Font_Analytics {
public function __construct() {
add_action('wp_footer', array($this, 'track_font_usage'));
add_action('admin_menu', array($this, 'add_analytics_page'));
}
public function track_font_usage() {
if (!current_user_can('manage_options')) {
return;
}
?>
<script>
(function() {
// 检测页面中使用的字体
var usedFonts = new Set();
// 检查所有元素的计算字体
var allElements = document.querySelectorAll('*');
allElements.forEach(function(el) {
var computedStyle = window.getComputedStyle(el);
var fontFamily = computedStyle.fontFamily;
if (fontFamily && fontFamily !== 'inherit') {
// 提取字体族名称(去除引号和备用字体)
var fonts = fontFamily.split(',')[0].replace(/['"]/g, '').trim();
if (fonts) {
usedFonts.add(fonts);
}
}
});
// 发送使用数据到服务器
if (usedFonts.size > 0) {
var data = {
action: 'track_font_usage',
fonts: Array.from(usedFonts),
page_url: window.location.href,
nonce: '<?php echo wp_create_nonce("font_analytics_nonce"); ?>'
};
// 使用navigator.sendBeacon确保数据发送
if (navigator.sendBeacon) {
var formData = new FormData();
for (var key in data) {
formData.append(key, data[key]);
}
navigator.sendBeacon('<?php echo admin_url("admin-ajax.php"); ?>', formData);
}
}
})();
</script>
<?php
}
public static function handle_usage_tracking() {
if (!wp_verify_nonce($_POST['nonce'], 'font_analytics_nonce')) {
wp_die('安全验证失败');
}
$fonts = isset($_POST['fonts']) ? array_map('sanitize_text_field', $_POST['fonts']) : array();
$page_url = sanitize_url($_POST['page_url']);
$user_id = get_current_user_id();
global $wpdb;
$usage_table = $wpdb->prefix . 'font_usage';
$fonts_table = $wpdb->prefix . 'custom_fonts';
foreach ($fonts as $font_family) {
// 查找字体ID
$font_id = $wpdb->get_var($wpdb->prepare(
"SELECT id FROM $fonts_table WHERE font_family = %s",
$font_family
));
if ($font_id) {
// 记录使用情况
$wpdb->insert(
$usage_table,
array(
'font_id' => $font_id,
'page_url' => $page_url,
'user_id' => $user_id
),
array('%d', '%s', '%d')
);
}
}
wp_die();
}
public function add_analytics_page() {
add_submenu_page(
'font-management',
'字体分析',
'字体分析',
'manage_options',
'font-analytics',
array($this, 'render_analytics_page')
);
}
public function render_analytics_page() {
?>
<div class="wrap">
<h1>字体使用分析</h1>
<div class="analytics-container">
<div class="analytics-stats">
<?php $this->display_font_statistics(); ?>
</div>
<div class="analytics-charts">
<canvas id="fontUsageChart" width="400" height="200"></canvas>
</div>
<div class="analytics-table">
<?php $this->display_font_usage_table(); ?>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
jQuery(document).ready(function($) {
var ctx = document.getElementById('fontUsageChart').getContext('2d');
var chart = new Chart(ctx, {
type: 'bar',
data: {
labels: <?php echo json_encode($this->get_font_labels()); ?>,
datasets: [{
label: '使用次数',
data: <?php echo json_encode($this->get_font_usage_data()); ?>,
backgroundColor: 'rgba(54, 162, 235, 0.5)',
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 1
}]
},
options: {
responsive: true,
scales: {
y: {
beginAtZero: true
}
}
}
});
});
</script>
<?php
}
private function display_font_statistics() {
global $wpdb;
$fonts_table = $wpdb->prefix . 'custom_fonts';
$usage_table = $wpdb->prefix . 'font_usage';
$total_fonts = $wpdb->get_var("SELECT COUNT(*) FROM $fonts_table WHERE is_active = 1");
$total_usage = $wpdb->get_var("SELECT COUNT(*) FROM $usage_table");
$most_used = $wpdb->get_row(
"SELECT f.font_family, COUNT(u.id) as usage_count
FROM $usage_table u
JOIN $fonts_table f ON u.font_id = f.id
GROUP BY u.font_id
ORDER BY usage_count DESC
LIMIT 1"
);
echo '<div class="stat-card">';
echo '<h3>活跃字体数量</h3>';
echo '<p class="stat-number">' . $total_fonts . '</p>';
echo '</div>';
echo '<div class="stat-card">';
echo '<h3>总使用次数</h3>';
echo '<p class="stat-number">' . $total_usage . '</p>';
echo '</div>';
if ($most_used) {
echo '<div class="stat-card">';
echo '<h3>最常用字体</h3>';
echo '<p class="stat-number">' . esc_html($most_used->font_family) . '</p>';
echo '<p class="stat-desc">使用次数: ' . $most_used->usage_count . '</p>';
echo '</div>';
}
}
}
add_action('wp_ajax_track_font_usage', array('Font_Analytics', 'handle_usage_tracking'));
add_action('wp_ajax_nopriv_track_font_usage', array('Font_Analytics', 'handle_usage_tracking'));
为内容编辑器和前端用户提供字体选择功能:
class Frontend_Font_Selector {
public function __construct() {
// 为古腾堡编辑器添加字体选择控件
add_action('enqueue_block_editor_assets', array($this, 'add_block_editor_font_controls'));
// 为经典编辑器添加字体下拉菜单
add_filter('mce_buttons_2', array($this, 'add_font_select_to_tinymce'));
add_filter('tiny_mce_before_init', array($this, 'customize_tinymce_fonts'));
// 前端字体选择器短代码
add_shortcode('font_selector', array($this, 'render_font_selector_shortcode'));
}
public function add_block_editor_font_controls() {
wp_enqueue_script(
'gutenberg-font-controls',
get_template_directory_uri() . '/js/gutenberg-font-controls.js',
array('wp-blocks', 'wp-element', 'wp-components', 'wp-editor', 'wp-data'),
'1.0.0',
true
);
// 传递可用字体列表
$active_fonts = $this->get_active_fonts();
wp_localize_script('gutenberg-font-controls', 'fontControlsData', array(
'fonts' => $active_fonts,
'defaultFont' => get_theme_mod('primary_font', 'Arial, sans-serif')
));
// 添加编辑器样式
$font_css_url = get_option('dynamic_font_css_path');
if ($font_css_url) {
wp_enqueue_style('editor-fonts', $font_css_url);
}
}
public function add_font_select_to_tinymce($buttons) {
array_unshift($buttons, 'fontselect');
return $buttons;
}
public function customize_tinymce_fonts($init) {
$active_fonts = $this->get_active_fonts();
$font_formats = '';
foreach ($active_fonts as $font) {
$font_formats .= $font['name'] . '=' . $font['family'] . ';';
}
// 添加默认字体
$font_formats .= 'Arial=arial,helvetica,sans-serif;';
$font_formats .= 'Times New Roman=times new roman,times,serif;';
$init['font_formats'] = $font_formats;
$init['fontsize_formats'] = "8px 10px 12px 14px 16px 18px 20px 24px 28px 32px 36px 48px";
return $init;
}
public function render_font_selector_shortcode($atts) {
$atts = shortcode_atts(array(
'type' => 'dropdown', // dropdown, preview, or inline
'category' => '',


