JavaScript可以改变@page CSS的值吗?

k0pti3hp  于 2023-01-19  发布在  Java
关注(0)|答案(3)|浏览(168)

下面的CSS会影响页面在默认情况下是纵向打印还是横向打印。

@page {
   size: landscape;
}

我意识到这只能在非常有限的浏览器上工作,而且用户可以覆盖它。我只是想提供一个好的默认。
这个值在CSS中作为一个静态值很好用,但是我想根据用户的选择在纵向和横向之间动态切换。可以使用JavaScript来改变这个值吗?

nx7onnlm

nx7onnlm1#

一个简单的方法是为@page创建一个单独的样式并对其进行更改:

var cssPagedMedia = (function () {
    var style = document.createElement('style');
    document.head.appendChild(style);
    return function (rule) {
        style.innerHTML = rule;
    };
}());

cssPagedMedia.size = function (size) {
    cssPagedMedia('@page {size: ' + size + '}');
};

cssPagedMedia.size('landscape');
pcww981p

pcww981p2#

@jasssonpet用他的回答救了我的小命,话虽如此,我还是把它改得简单一点(在我看来)。

**不太清楚为什么要这样做,但如果你知道,请告诉我。如果只是偏好,那么我分享我的代码样本是因为其他人的偏好可能更符合我的偏好。

// just create the style tag and set the page size
function setPageSize(cssPageSize) {
    const style = document.createElement('style');
    style.innerHTML = `@page {size: ${cssPageSize}}`;
    document.head.appendChild(style);
}

// how to use it
setPageSize('letter landscape');

编辑:这是我最近第一次登录,看到了@jasssonpet的答案,现在我觉得更有意义了。如果其他人感到困惑,他的方法的主要好处是两件事:
1.他使用闭包,这样只有一个样式标签添加到页面中,然后可以引用和更改。
1.他对cssPagedMedia进行了扩展,使添加的任何方法都具有名称空间,这样,全局名称空间就不会受到污染。
下面是它的类形式(我发现它更容易理解):

class SingletonStyle {
  constructor() {
    this.style = document.createElement("style");
    document.head.appendChild(this.style);
  }

  apply(rule) {
    this.style.innerHTML = rule;
  }

  size(size) {
    this.apply("@page {size: " + size + "}");
  }
}
ig9co6j1

ig9co6j13#

感谢@jasssonpet的解决方案!我遇到了一个问题,Vue JS无法在root之外v-bindcss,如下所示

@media print {
  @page {
    size: A4 v-bind(printSize); // <-- doesn't work!
  }
}

我需要独立地管理方向和边距,也许将来会有更多的规则。因此,我重新编写并更新了该代码,以便嵌入其他代码和框架。
utils/customizePageStyle.js

let pageStyle;
const pageRules = {};

const pageHasRules = () => !!Object.keys(pageRules).length;

const addCustomCssStylesheet = async () => {
  pageStyle = document.createElement('style');
  document.head.appendChild(pageStyle);
};

export const cleanPageRules = () => pageStyle.innerHTML = `@page {}`;

const writePageRules = async () => {
  if (!pageStyle) await addCustomCssStylesheet();
  if (!pageHasRules) {
    cleanPageRules();
    return;
  }
  let styleTxt = '@media print { @page {';
  Object.keys(pageRules).forEach(ruleName => {
    const ruleTxt = pageRules[ruleName];
    styleTxt += `${ruleName}: ${ruleTxt} !important; `;
  });
  styleTxt += '} } ';
  pageStyle.innerHTML = styleTxt;
};

const addPageRule = ({ruleName, ruleValue}) => pageRules[ruleName] = ruleValue;

const asyncAddPageRule = async rule => {
  addPageRule(rule);
  await writePageRules();
};

const addPageRules = async rules => {
  rules.forEach(rule => addPageRule(rule));
  await writePageRules();
};

const delPageRule = ruleName => pageRules[ruleName] = null;

const asyncDelPageRule = async ruleName => {
  delPageRule(ruleName);
  await writePageRules();
};

const delPageRules = async ruleNames => {
  ruleNames.forEach(ruleName => delPageRule(ruleName));
  pageHasRules ? await writePageRules() : cleanPageRules();
};

export const setPageRules = {
  add: asyncAddPageRule,
  adds: addPageRules,
  del: asyncDelPageRule,
  dels: delPageRules,
  clean: cleanPageRules
};

Vue J使用示例:

<script setup>
import { setPageRules } from '@/utils/customizePageStyle.js';
const printSize = computed(()=> yourCondition1 ? 'A4 portrait' : 'A4 landscape');
const printMargin = computed(()=> yourCondition2 ?
  '1cm 1cm 1cm 2cm' : '24pt 24pt auto 18pt');
onMounted(()=> {
  window.addEventListener('beforeprint', async e => {
    await setPageRules.adds([
      {ruleName: 'size', ruleValue: printSize.value},
      {ruleName: 'margin', ruleValue: printMargin.value},
    ]);
  });
  window.addEventListener('afterprint', e => setPageRules.clean());
}
</script>
<style>
@media print {
  body {
    margin: 0px; // don't work with it, I don't know why
  }
}

相关问题